python - 别名 self = super(...).__new__(...)?为什么?

标签 python python-3.x immutability self super

我写了一个mixed number fraction class扩展和扩展标准库 Fraction 类的功能,以便接受 Fraction 会接受的任何内容以及更多:Mixed('3 4/5') == 混合(3,4,5) == 混合(分数(19,5)) == 分数(19,5) 等。我已经阅读了很多关于 super 的内容,但我仍然不能 100% 确定我理解 Fraction 类中这一行的内容和原因来源 __new__ 定义:

self = super(Fraction, cls).__new__(cls)

我怀疑它使每个对 self 的引用都指向并创建一个新的 Fraction 实例,因为该类是不可变的。这是正在发生的事情吗?为什么?

最佳答案

super(Fraction, cls).__new__ 将通过类 MRO 查找 next .__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__ 方法声明的目的是创建一个新实例。因为数字确实是不可变的,这就是您想要 Hook 的地方,以便能够自定义实例的创建方式,因为一旦它存在,就无法再更改。

名称self 只是一个本地名称。它符合方法使用的约定,但__new__ 不是普通的绑定(bind)方法,因为在创建新实例时没有要绑定(bind)到 的东西。您可以在整个函数中用完全不同的东西(instancethis_new_object_we_just_created 等)替换该名称,代码仍然可以正常工作。 other 函数中的 self 不受其影响。

碰巧,Fraction 实例可变的;该类定义了 _numerator_denominator 槽,它们在创建实例后仍然可以重新绑定(bind)。 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

但如您所见,如果您知道可变属性,您仍然可以从外部改变实例。

关于python - 别名 self = super(...).__new__(...)?为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20003651/

相关文章:

python - 在 hadoop 中将附加文件附加到 python 流作业

python - Pandas Dataframe - 将字符串拆分为多列

python - 将数据帧以羽化格式保存到 S3

java - 有什么好方法可以让不可变对象(immutable对象)链循环起来吗?

java - 最终的、不可变的对象不是常量吗?

Python Numpy : Extracting a row from an array

python - 如何仅为最后一次出现的重复行识别并设置列值

python - 包含一列列表的 Pandas DataFrame 中的行重复 (Python3)

Python从xhtml中抓取属性值:link

java - 如果 java 类具有另一个用户定义类的成员变量,我们如何使其不可变?