2015-12-02 27 views
0

我試圖使用Python的__new__爲了在實例化類時返回與實際對象實例不同的東西(無論這是否巧妙是一個不同的討論)。下面是一個最簡單的例子,其中我返回了來自__new__的兩個類實例的列表,而不是實際的類實例。無法創建新的對象實例重寫__new__

from copy import deepcopy 

class TestClass: 

    def __new__(self, param=None): 

     self.__init__(self, param=param) 

     return [deepcopy(self), deepcopy(self)] 

    def __init__(self, param=None): 
     self.param = param 


if __name__ == '__main__': 
    a = TestClass(param=1) 
    b = TestClass(param=2) 
    print(a[0].param) # prints 2! 

然而,看來我不能用這種方法來創建實際的對象實例,因爲可以在最小的例子可以看出。 print語句應打印1,但打印2,表示傳遞給第二次調用TestClass的參數將覆蓋第一個調用的參數。我的猜測是ab引用了同樣的static class TestClass,而我的deepcopy也沒有幫助,因爲它對靜態類沒有意義。

如何修改__new____init__TestClass這樣我實際上創建了新的實例(即print語句應該打印1而不是2)?

(Python的3.5)

編輯/小澄:我其實不想TestClass的是靜態的(如果這是正確的行話反正),但我的非功能性的實現似乎產生像靜態類。

解決方案

感謝凱,下面的代碼工作:

class TestClass(object): 

    def __new__(cls, param): 

     instance1 = object.__new__(cls) 
     instance1.__init__(param) 
     instance2 = object.__new__(cls) 
     instance2.__init__(param) 

     return instance1, instance2 

    def __init__(self, param): 
     self.param = param 
+1

https://docs.python.org/3/reference/datamodel.html#object.__new__ –

回答

2

您撥打的第一個參數__new__self,但它實際上是類,通常被稱爲cls。所以你正在寫信給班上,而不是實例。

真正得到兩個實例使用:

class X(object): 
    def __new__(cls, param): 
     self1 = object.__new__(cls) 
     self1.__init__(param) 
     self2 = object.__new__(cls) 
     self2.__init__(param) 
     return self1, self2 

不能使用deepcopy的,因爲它會調用X.__new__()(不param參數),這將導致一個循環。

+0

'回報self1,self2' - 這是沒有意義的.... –

+0

@KarolyHorvath,OP承認可疑的任務感。因爲你不應該在生產中這樣做。但是如果你只想學習'__new__'的含義,那麼我猜這個問題是可以接受的。 – kay

+1

@KarolyHorvath爲什麼不呢? OP希望'TestClass(1)'給出一個元組的'TestClass'類型的兩個對象,其屬性'param'等於'1'。這是奇怪的,也不是我想在野外遇到的,但它是一個有效的學習工具。 –

2

如果您使用__new__的正確參數,將會突出顯示導致param在全班級共享的特定問題。正如@Kay在他的回答中提到的,__new__接受一個類作爲第一個參數,而不是一個實例。

class Foo(object): 
    def __new__(cls, param): 
     cls.__init__(cls, param=param) 

這是錯誤的,因爲那麼它遵循__init__獲得一個類時,預計一個實例。

def __init__(self, param): 
    # remember that `self` here is `Foo`! so... 
    self.param = param 
    # ...means Foo.param = param, setting it class-wide! 
+0

謝謝,這幫助我理解! – monade