在类内生成新对象的惯用Python方式
我有一个对象的方法,这个方法会返回一个该类的新实例。我想找出一种最合适的写法,让这个方法能生成同类型的新对象,而不需要重复代码。
因为这个方法使用了实例中的数据,我的初步想法是:
class Foo(object):
def get_new(self):
data = # Do interesting things
return Foo(data)
但是,如果我创建了一个Foo的子类,而没有重写get_new方法,那么在SubFoo上调用get_new时,返回的还是Foo对象!所以,我可以写一个类方法:
class Foo(object):
@classmethod
def get_new(cls, obj):
data = # Munge about in objects internals
return cls(data)
不过,我访问的数据是特定于对象的,这样做似乎会破坏封装性,不应该是一个“普通的”(没有装饰的)方法。此外,这样调用时就得像 SubFoo.get_new(sub_foo_inst)
这样,感觉有点多余。我希望对象能“知道”自己应该返回哪种类型——就是和它自己一样的类型!
我想也可以给类添加一个工厂方法,然后在各个地方重写返回类型,而不需要重复逻辑,但这似乎会给子类带来很多工作。
所以,我的问题是,怎么写一个方法,既能灵活处理类的类型,又不用到处标注类型呢?
2 个回答
3
你可以使用内置的'type'。
type(instance)
这就是这个实例的类。
24
如果你想让子类更灵活一点,可以简单地使用 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)
,因为这会给出一个不合适的值,特别是对于那些没有从基本的 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__
更符合 Python 的风格。