Re: [問題] class str繼承問題

看板Python作者 (殘雲奪月)時間10年前 (2013/12/29 16:46), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串2/2 (看更多)
這問題簡單的回答是 str.__new__ 這個方法只接受一個參數,而你給他三個。 實驗: 這兩行 str.__new__(str) 和 str.__new__(str, '1') 程式碼不會出錯 然而 str.__new__(str, '1', '2') 會出現 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: str() takes at most 1 argument (2 given) 細節: 當 class 要產生 instance 時,他會呼叫 class 的 metaclss 的 __call__ 方法 而 metaclass 的 __call__ 方法大概長這樣 def __call__(cls, *args, **kwargs): obj = cls.__new__(cls, *args, **kwargs) obj.__init__(*args, **kwargs) return obj 所以你的程式 s = S(1,2,3) 直譯器會先做 obj = str.__new__(str, *args, **kwargs) 其中 *args 是 (1, 2, 3) 可是因為 str.__new__ 只接受一個參數,因此發生錯誤 觀察: class ClsA(object): def __init__(self, *args, **kwargs): print 'init: ', args, kwargs def __new__(cls, *args, **kwargs): print 'new: ', args, kwargs return super(ClsA, cls).__new__(cls, *args, **kwargs) a = ClsA('a', 'b', 2) 上面程式碼,當要建立 ClsA 的程式碼,他會先執行 __new__, 而餵給 __new__ 的參數則是 ClsA 後面的參數。 之後再把 ClsA 後面的參數餵給 __init__ 問題解決方法: 由於問題出現在餵給 str.__new__ 太多參數,因此我們不要讓他有太多參數 解法1. 不要使用預設的 metaclass(type),自訂一個 meta class class CustomMetaCls(type): def __call__(cls, *args, **kwargs): if len(args): content = args[0] else: content = '' obj = cls.__new__(cls, content) obj.__init__(*args, **kwargs) return obj class MyStr(str): __metaclass__ = CustomMetaCls def __init__(self, a='', b=''): super(MyStr, self).__init__(a) self.a = a self.b = b b = MyStr('a', 'b') 解法2. override __new__ class MyStr1(str): def __init__(self, a='', b=''): super(MyStr1, self).__init__() self.a = a self.b = b def __new__(cls, *args, **kwargs): print args, kwargs if len(args): content = args[0] else: content = '' return str.__new__(cls, content) 參考資料: http://www.slideshare.net/hychen/python-type-and-object 或是 tainan.py 12月份的錄影 有錯敬請指教 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 36.225.27.98 ※ 編輯: ya790206 來自: 36.225.27.98 (12/29 17:07)
文章代碼(AID): #1Il-5lSh (Python)
文章代碼(AID): #1Il-5lSh (Python)