- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试创建一个新的不可变类型,类似于内置的 Fraction
但不是派生自它。分数类 is created like this :
# We're immutable, so use __new__ not __init__
def __new__(cls, numerator=0, denominator=None):
...
self = super(Fraction, cls).__new__(cls)
self._numerator = ...
self._denominator = ...
return self
但是我看不出这和
有什么不同def __init__(self, numerator=0, denominator=None):
...
self._numerator = ...
self._denominator = ...
创建 2 个具有相同值的 (实际上在评论中指出它是执行此操作的类型并不常见。)Fraction
对象不会创建指向相同对象/内存位置的 2 个标签
尽管有源代码注释,但它们实际上并不是不可变的:
f1 = Fraction(5)
f2 = Fraction(5)
id(f1), id(f2)
Out[35]: (276745136, 276745616)
f1._numerator = 6
f1
Out[41]: Fraction(6, 1)
f2
Out[42]: Fraction(5, 1)
id(f1)
Out[59]: 276745136
那么这样做有什么意义呢?
文档说
__new__()
is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.
因此,如果我不是对内置类型进行子类化,而是从头开始创建不可变类型(object
的子类),我还需要使用它吗?
最佳答案
如果你正在制作一个真正不可变的类型,你应该使用 __new__
,因为传递给 __init__
的 self 对象在逻辑上已经是不可变的了,因此将值分配给其成员为时已晚。这对于那些编写子类的人来说更加激烈,因为添加成员将被禁止。
由于不可变性实际上不是内在属性,而是一种技巧,通常通过 Hook __setattr__
来强制执行,因此人们确实编写了使用 __init__
然后 初始化的不可变类型 通过设置一些成员使自己不可变,然后使设置其他成员变得不可能。但这种情况下的逻辑可能会变得相当曲折,__setattr__
可能会充满额外的规则。
拥有某种可变类型并从中继承不可变类型的 __setattr__
版本更有意义,它只是引发包含在子类。这使得使用 __new__
的逻辑显而易见。由于它可以生成可变父类(super class)并对其进行修改,然后将其作为继承类型返回,因此不会造成混淆。
如果 Fraction 打算是不可变的,那么实现者要么错过了这一步,要么后来想得更好而忘记删除他们的评论。
>>> class Pair(object):
... def __init__(self, key, value):
... self.key = key
... self.value = value
...
>>> class ImPair(Pair):
... def __new__(cls, key, value):
... self = Pair(key, value)
... self.__class__ = cls
... def __setattr__(self, name, value):
... raise AttributeError(name)
...
>>> x = Pair(2,3)
>>> x.key
2
>>> x.key = 9
>>> x.key
9
>>> x = ImPair(2,3)
>>> x.key
2
>>> x.key = 9
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __setattr__
AttributeError: key
>>>
关于python - 为什么 Fraction 使用 __new__ 而不是 __init__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25901904/
为什么正是是 A.__init__() B.__init__() D.__init__() 由以下代码打印?特别是: 为什么是C.__init__() 未打印? 为什么是C.__init__()如果我
目前我有这样的事情: @dataclass(frozen=True) class MyClass: a: str b: str c: str d: Dict[str, str] ...
我正在尝试从父类继承属性: class Human: def __init__(self,name,date_of_birth,gender,nationality): self.name =
如何扩展基类的 __init__,添加更多要解析的参数,而不需要 super().__init__(foo, bar) 在每个派生类中? class Ipsum: """ A base ips
这是我试图解决的一个非常简单的例子: class Test(object): some_dict = {Test: True} 问题是我无法在 Test 仍在定义时引用它 通常,我会这样做:
我在 Objective-C 中使用过这个结构: - (void)init { if (self = [super init]) { // init class }
我有一个类层次结构,其中 class Base 中的 __init__ 执行一些预初始化,然后调用方法 calculate。 calculate 方法在 class Base 中定义,但预计会在派生类
这是我在多种语言中都怀念的一个特性,想知道是否有人知道如何在 Python 中完成它。 我的想法是我有一个基类: class Base(object): def __init__(self):
我正在对 threading.Thread 类进行子类化,它目前看起来像这样: class MyThread(threading.Thread): def __init__(self:
我正在用 cython 写一些代码,我有一些 "Packages “within” modules" . — 这实际上是对我在那里的问题的跟进,结构应该是一样的。问题是这是 cython,所以我处理的
class AppendiveDict(c.OrderedDict): def __init__(self,func,*args): c.OrderedDict.__init_
看完this回答,我明白 __init__ 之外的变量由类的所有实例和 __init__ 内的变量共享每个实例都是唯一的。 我想使用所有实例共享的变量,随机给我的类实例一个唯一的参数。这是我尝试过的较
在下面的代码中: import tkinter as tk class CardShuffling(tk.Tk): background_colour = '#D3D3D3'
我正在覆盖类的 __new__() 方法以返回具有特定 __init__() 集的类实例。 Python 似乎调用类提供的 __init__() 方法而不是特定于实例的方法,尽管 Python 文档在
从内置类型和其他类派生时,内置类型的构造函数似乎没有调用父类(super class)构造函数。这会导致 __init__ 方法不会被 MRO 中内置函数之后的类型调用。 例子: class A:
答: super( BasicElement, self ).__init__() 乙: super( BasicElement, self ).__init__( self ) A 和 B 有什么区
class A(object): def __init__(self): print('A.__init__()') class D(A): def __init__(
到目前为止我已经成功地做了什么: 我创建了一个 elem 类来表示 html 元素(div、html、span、body 等)。 我可以像这样派生这个类来为每个元素创建子类: class elem:
我一直在努力理解 super() 在多重继承的上下文中的行为。我很困惑为什么在 test2.py 的父类中调用 super() 会导致为父类调用 __init__()? test1.py #!/usr
为什么我在 Python 代码中看不到以下内容? class A: def __init__(self, ...): # something important class B
我是一名优秀的程序员,十分优秀!