我写了mixed number fraction class来扩展和扩展标准库Fraction
类的功能,以便接受Fraction
会更多的内容:Mixed('3 4/5')
== { {1}} == Mixed(3,4,5)
== Mixed(Fraction(19,5))
等我已经阅读了很多关于Fraction(19,5)
的内容,我仍然不能100%确定我理解这是什么以及为什么super
类来源Fraction
定义中的一行:
__new__
我怀疑它会使self = super(Fraction, cls).__new__(cls)
的每个引用指向并创建self
的新实例,因为该类是不可变的。这是发生了什么,为什么?
答案 0 :(得分:3)
super(Fraction, cls).__new__
会查看MRO类以查找下一个 .__new__
方法,从Fraction
的位置开始搜索一步:< / p>
>>> 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
但正如您所看到的,如果您了解可变属性,您仍然可以从外部改变实例。