2011-02-14 92 views
11

我在其中一个对象上创建了一个方法,该方法返回该类的新实例。我试图找出最常用的方法来编写这种方法,以便它可以生成相同类型的新对象而不会重复代码。用于在类中生成新对象的习惯用法

由于这种方法从实例使用的数据,我第一遍是:

class Foo(object): 
    def get_new(self): 
     data = # Do interesting things 
     return Foo(data) 

但是,如果我继承Foo和不get_new覆盖,呼吁get_new上SubFoo将返回一个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),这似乎是多余的。我希望对象只是“知道”返回哪种类型 - 与它自己的类型相同!

我想也可以向类中添加一个工厂方法,并在任何地方重写返回类型,而不重复逻辑,但似乎在子类上做了很多工作。

所以,我的问题是,编写一种方法的最佳方法是什么,它提供了类的类型灵活性,而不必在整个地方注释类型?

+0

classmethods本身在Python上不是很习惯用法;工厂可以只是简单的功能,与班级生活在同一个模块中。 – 2011-02-14 19:52:18

+1

@Adam:类方法有其用途(例如,当您使用类变量并且不想破坏继承时)。静态方法更糟糕。 – delnan 2011-02-14 19:56:38

回答

16

如果你想它的子类更灵活,你可以简单地使用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,I不建议使用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更成语。

2

您可以使用内建'类型'。

type(instance) 

是该实例的类。