我只是想简化我的一个类,并引入了一些与flyweight设计模式相同的功能.
但是,我有点困惑,为什么__init__总是被称为__new__.我没想到这个.任何人都可以告诉我为什么会这样,以及我如何能够实现这个功能呢?(除了将实施放入__new__感觉相当hacky之外.)
这是一个例子:
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
Run Code Online (Sandbox Code Playgroud)
输出:
NEW
INIT
EXISTS
INIT
EXISTS
INIT
Run Code Online (Sandbox Code Playgroud)
为什么?
在Python中,__new__用于初始化不可变类型,__init__通常初始化可变类型.如果__init__从语言中删除,那么就不能再轻松完成了什么?
例如,
class A:
def __init__(self, *, x, **kwargs):
super().__init__(**kwargs)
self.x = x
class B(A):
def __init__(self, y=2, **kwargs):
super().__init__(**kwargs)
self.y = y
Run Code Online (Sandbox Code Playgroud)
可以__new__像这样重写:
class A_N:
def __new__(cls, *, x, **kwargs):
obj = super().__new__(cls, **kwargs)
obj.x = x
return obj
class B_N(A_N):
def __new__(cls, y=2, **kwargs):
obj = super().__new__(cls, **kwargs)
obj.y = y
return obj
Run Code Online (Sandbox Code Playgroud)
澄清问题范围:这不是关于如何使用__init__和__new__使用它们或它们之间有什么区别的问题.这是一个关于如果__init__从语言中删除会发生什么的问题.什么事情会破裂?有什么事情会变得更难或不可能吗?
我有以下课程:
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__吗?
我认为你可以在一个类中定义' __init__'或' __new__',但为什么在django.utils.datastructures.py中定义了所有.
我的代码:
class a(object):
def __init__(self):
print 'aaa'
def __new__(self):
print 'sss'
a()#print 'sss'
class b:
def __init__(self):
print 'aaa'
def __new__(self):
print 'sss'
b()#print 'aaa'
Run Code Online (Sandbox Code Playgroud)
datastructures.py:
class SortedDict(dict):
"""
A dictionary that keeps its keys in the order in which they're inserted.
"""
def __new__(cls, *args, **kwargs):
instance = super(SortedDict, cls).__new__(cls, *args, **kwargs)
instance.keyOrder = []
return instance
def __init__(self, data=None):
if data is None:
data = {}
super(SortedDict, self).__init__(data)
if isinstance(data, dict):
self.keyOrder = …Run Code Online (Sandbox Code Playgroud) 这个问题与this,this,this和this有关,但不是重复的。这些链接在这里没有回答我的问题。但是,这几乎可以回答我的问题,但不能回答,因为答案中的代码无法在Python 3.6中运行,而且无论如何该问题都不是我在这里问的具体问题。(请参阅下面的我自己的答案。
从Python的文档页面,我发现下面的文字。
__new__()主要用于允许不可变类型的子类(例如int,str或tuple)自定义实例创建。为了自定义类的创建,它通常也被自定义元类覆盖。
但是为什么呢?为什么我们不能仅覆盖__init__()而不是必须覆盖__new__()?显然,frozenset例如,甚至没有实现__init__();为什么呢?我从了解这里,在某些罕见的情况下,__new__()并且__init__()需要做不同的事情,但据我可以看到,封装状态中只有。是什么样的不可变的类型,特别需要使用的__new__(),而不是__init__()?
python ×5
class ×1
class-design ×1
constructor ×1
immutability ×1
python-3.x ×1
set ×1
subclass ×1