2014-04-04 30 views
1
class A(): 
    ... 

我想通過這門課A是與任何對象作爲參數初始化,但是當__init__去與A類型,它應該離開/返回舊A對象,不創建包裝A(A())如何防止包裝對象自行包裝?

我想覆蓋__new__方法是解決方法,但如何停止創建object creator並返回給定的參數作爲結果。

我的解決辦法,現在只是推薦:

def ToA(it): 
    if type(it) == A: 
     return it 
    else: 
     return A(it) 

但我需要某種方式塊以A防止直接使用A(A())

+0

這看起來像一個裝飾者。 – 2rs2ts

+0

我認爲你唯一的兩個選擇就是你提到的選項:類中的__new__或轉換方法。根據您的使用情況,可能'__new__'最有意義。 – Claudiu

回答

0

我不敢肯定我明白你想要什麼,但是像這樣的可能就是吧。用這種技術你不能有一個__init__,因爲如果你這樣做,它將被稱爲而不管是否__new__返回一個新的對象。

class A(object): 
    def __new__(cls, obj): 
     if isinstance(obj, cls): 
      return obj 
     rv = object.__new__(cls) 

     # everything you would normally put in __init__ 
     # goes here instead 
     rv._obj = obj 
     return rv 

    # for instance: 
    def __repr__(self): 
     return "A({})".format(repr(self._obj)) 

>>> A() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __new__() takes exactly 2 arguments (1 given) 
>>> A(1) 
A(1) 
>>> A(A(1)) 
A(1) 

不能夠使用__init__是麻煩的,特別是如果你需要繼承A。這裏有一個方法來解決是:

class A(object): 
    def __new__(cls, obj): 
     if isinstance(obj, cls): 
      return obj 
     rv = object.__new__(cls) 
     rv._initialized = False 
     return rv 

    def __init__(self, obj): 
     if self._initialized: return 
     self._obj = obj 
     self._initialized = True 

class B(A): 
    def __init__(self, obj): 
     if self._initialized: return 
     A.__init__(self, obj) 
     self._otherthing = "foo" 

你必須檢查self._initialized在每個子類中的方法__init__,很遺憾。

+0

不錯的訣竅,我只用'__new__''作爲檢查類型,然後休息在''__init__''中 - 我的錯誤。 –

+0

現在我發現你應該使用'isinstance(obj,cls)'而不是'type(obj)是cls' - 如果'A'曾經被子類化,後者將無法正常工作。 – zwol

+0

瞭解。我必須記住不要在任何子類中添加'__init__'' - 有點問題。 –