想搞一個對象繼承自str,然后存一些額外信息用來標識這個字符串,然后理所當然地重寫了__init__發現跪了:
class newstring(str): def __init__(self, value, othervalue): str.__init__(self, value) self.othervalue = othervalue astring = newstring('hello', 'othervalue') # Fail
后來發現str的__new__是在__init__前調用的,然后str在__new__的時候發現參數不對就拋了個異常。這么詭異的行為主要是因為str的__new__就返回了個新的實例,而__init__沒毛用。Python里面的str大概是這個樣子:
class newstring(str): def __new__(cls, value): return str.__new__(cls, value) def __init__(self, value): pass
那么想要繼承str並在構造時增加一個參數咋整呢,可以重寫__new__:
class newstring(str): def __new__(cls, value, othervalue): return str.__new__(cls, value) def __init__(self, value, othervalue): self.othervalue = othervalue
或者更簡單粗暴的,用*args和**kwargs作為參數重寫__new__以繞過__new__的參數檢查,然后__init__就可以正常調用了:
class newstring(str): def __new__(cls, value, *args, **keywargs): return str.__new__(cls, value) def __init__(self, value, othervalue): self.othervalue = othervalue
然后這樣構造的newstring長的跟str一個樣,並且可以攜帶額外信息,有一點需要注意,就是str是個不可變對象,所以newstring構造出來后就別YY能修改它的值了…