2010-06-25 80 views
12

我有以下類:Python中,繼承不變類型

class MySet(set): 

    def __init__(self, arg=None): 
     if isinstance(arg, basestring): 
      arg = arg.split() 
     set.__init__(self, arg) 

可正常工作(初始化設定以字符串的話,而不是字母)。然而,當我想要做一套一成不變的版本一樣,__init__方法似乎被忽略:

class MySet(frozenset): 

    def __init__(self, arg=None): 
     if isinstance(arg, basestring): 
      arg = arg.split() 
     frozenset.__init__(self, arg) 

我可以實現與__new__類似的東西?

+1

我認爲'__new __(..)'採取主動的原因,當談到雕刻不可變類型的實例是利用不變性,並保留一個機會返回現有的實例(如果可用)。 (但是如果一個人不想要這個優點,那麼他們可以在不干擾'__new __(..)'的情況下創建一個不可變類型,特別是'__new __(..)'不提供任何特殊的上下文。必須通過'object .__ setattr __(..)'或類似的方法來修改不可變字段,無論是在'__new __(..)'還是'__init _(..)'中。) – 2015-07-29 12:37:36

回答

12

是的,你需要重寫__new__特殊方法:

class MySet(frozenset): 

    def __new__(cls, *args): 
     if args and isinstance (args[0], basestring): 
      args = (args[0].split(),) + args[1:] 
     return super (MySet, cls).__new__(cls, *args) 

print MySet ('foo bar baz') 

,輸出是:

MySet(['baz', 'foo', 'bar']) 
+0

超! 是否可以__init__被棄用? – EoghanM 2010-06-25 22:38:10

+4

@EoghanM:不,'__new__'是不同的。基本上,'__new__'創建*或*查找實例,而'__init__'設置已經創建的實例。覆蓋'__new__'的主要原因是爲了避免創建新的實例(例如,使'SomeType()'總是返回相同的單例對象),或者爲某些不可變類型(如'frozenset')創建子類。有關詳細信息,請參閱http://docs.python.org/reference/datamodel.html#special-method-names。 – doublep 2010-06-25 22:55:43

+0

thx - 我的子問題在這裏更清楚地提出:http://stackoverflow.com/questions/3131488/ – EoghanM 2010-06-28 10:07:04