super(Fraction, cls).__new__
將尋找通過類MRO去尋找下一個.__new__
方法,從開始的Fraction
位置上搜索一個步:
>>> from fractions import Fraction
>>> Fraction.mro()
[<class 'fractions.Fraction'>, <class 'numbers.Rational'>, <class 'numbers.Real'>, <class 'numbers.Complex'>, <class 'numbers.Number'>, <class 'object'>]
所以它會考慮所有的其他類要查看下一個__new__
的定義,代碼然後調用它。最終,那將是object.__new__
,在Python的C代碼創建形成數字對象的實際C結構:
>>> for cls in Fraction.mro()[1:]:
... if '__new__' in cls.__dict__:
... print(cls)
...
<class 'object'>
的__new__
法的規定目的是創建一個新的實例。而且由於數字確實是不可變的,所以您希望能夠自定義實例的創建方式,因爲數字一旦存在就不能再被修改。
名稱self
只是一個本地名稱。它與方法使用的約定相匹配,但__new__
不是一種常規綁定方法,因爲在創建新實例時沒有什麼可以綁定到。您可以使用完全不同的東西(instance
,this_new_object_we_just_created
等)在整個函數中替換該名稱,並且代碼仍然可以工作。 self
在其他函數不受它的影響。
碰巧,Fraction
實例是可變;該類定義了_numerator
和_denominator
插槽,在創建實例後仍然可以反彈。 Fraction.__new__()
工廠方法實際上是這樣做的;它爲這些屬性分配新的值。調整這些屬性後,返回self
,從而履行__new__
方法的合同,返回新實例。
原則上,設置_numerator
和_denominator
屬性也都可以在__init__
方法中完成。然而,Python開發者已經決定要堅持公約恆定類型作爲類是意思被視爲一成不變的:
>>> fraction = Fraction(3, 4)
>>> fraction.numerator
3
>>> fraction.numerator = 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> fraction._numerator = 4
>>> fraction.numerator
4
,但你可以看到,如果你知道可變屬性,你可以仍然從外部突變實例。
'self'是一個**局部變量**;而這個名字只是一個慣例。你爲什麼認爲對這個實例的每一個其他引用都會指向它不應該的東西? –
請記住'__new__'是實例工廠。它產生一個新的實例,但只有當你調用正確的'type .__ new__'父方法時,它纔會返回創建的實例。 –