我的一个对象上有一个方法,它返回同一个类的新实例。我试图找出最惯用的方法来编写这个方法,这样它就可以生成一个相同类型的新对象而不需要复制代码。
由于此方法使用来自实例的数据,因此我的第一个传递是:
class Foo(object):
def get_new(self):
data = # Do interesting things
return Foo(data)
但是,如果我将Foo子类化并且不覆盖get_new,则在SubFoo上调用get_new将返回Foo!所以,我可以写一个classmethod:
class Foo(object):
@classmethod
def get_new(cls, obj):
data = # Munge about in objects internals
return cls(data)
但是,我正在访问的数据是特定于该对象的,因此它似乎打破了封装,因为它不是一个“正常”(未修饰)的方法。此外,您必须将其称为SubFoo.get_new(sub_foo_inst)
,这似乎是多余的。我希望对象只是“知道”返回哪种类型 - 与自身类型相同!
我想也可以在类中添加一个工厂方法,并在任何地方覆盖返回类型,而不重复逻辑,但这似乎在子类上做了很多工作。
所以,我的问题是,编写一个方法的最佳方法是什么,它提供了类的类型的灵活性,而无需在整个地方注释类型?
答案 0 :(得分:19)
如果您想让它更灵活地进行子类化,您只需使用self.__class__
特殊属性:
class Foo(object):
def __init__(self, data):
self.data = data
def get_new(self):
data = # Do interesting things
return self.__class__(data)
请注意,使用@classmethod
方法会阻止您访问任何一个实例中的数据,在#Do interesting things
依赖实例中存储的数据的情况下将其删除为可行的解决方案。
对于Python 2,我不建议使用type(self)
,因为这会为classic classes返回一个不合适的值(即那些未从基类object
中继承的值):
>>> class Foo:
... pass
...
>>> f = Foo()
>>> type(f)
<type 'instance'>
>>> f.__class__ # Note that the __class__ attribute still works
<class '__main__.Foo'>
对于Python 3,这不是一个问题,因为所有类都派生自object
,但是,我相信self.__class__
被认为是更像Pythonic的习语。
答案 1 :(得分:2)
您可以使用内置“类型”。
type(instance)
是该实例的类。