2011-02-14 93 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) 

是該實例的類。