我了解都__init__和__new__工作.我想知道是否有什么__init__可以做到的__new__不可以?
即可以使用__init__以下模式替换:
class MySubclass(object):
def __new__(cls, *args, **kwargs):
self = super(MySubclass, cls).__new__(cls, *args, **kwargs)
// Do __init__ stuff here
return self
Run Code Online (Sandbox Code Playgroud)
我问,因为我想让Python OO的这个方面更适合我.
我有以下课程:
class MySet(set):
def __init__(self, arg=None):
if isinstance(arg, basestring):
arg = arg.split()
set.__init__(self, arg)
Run Code Online (Sandbox Code Playgroud)
这可以按预期工作(用字符串而不是字母初始化集合).但是,当我想对set的不可变版本执行相同操作时,该__init__方法似乎被忽略:
class MySet(frozenset):
def __init__(self, arg=None):
if isinstance(arg, basestring):
arg = arg.split()
frozenset.__init__(self, arg)
Run Code Online (Sandbox Code Playgroud)
我可以实现类似的东西__new__吗?
我正在尝试创建一个新的不可变类型,类似于内置Fraction但不是从它派生的.Fraction类的创建方式如下:
# 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
Run Code Online (Sandbox Code Playgroud)
但我不知道这有什么不同
def __init__(self, numerator=0, denominator=None):
...
self._numerator = ...
self._denominator = ...
Run Code Online (Sandbox Code Playgroud)
创建 (实际上,在注释中指出,类型执行此操作并不常见.)Fraction具有相同值的2个对象不会创建指向同一对象/内存位置的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
Run Code Online (Sandbox Code Playgroud)
那么这样做有什么意义呢?
文档说
__new__()主要用于允许不可变类型的子类(如int,str或tuple)自定义实例创建.它也通常在自定义元类中重写,以自定义类创建.
因此,如果我不是内置类型的子类,但是我从头开始创建一个不可变类型(子类object),我还需要使用它吗?