Python 允许deafult构造函数接受一个实例并返回它而不受约束
我想让我的类构造函数接受这个类的一个实例,在这种情况下,返回这个相同的实例,而不是创建一个新的对象。就像Python 允许deafult构造函数接受一个实例并返回它而不受约束,python,python-3.x,default-constructor,Python,Python 3.x,Default Constructor,我想让我的类构造函数接受这个类的一个实例,在这种情况下,返回这个相同的实例,而不是创建一个新的对象。就像tuple所做的那样: >>> t = (1, 2, 3) >>> tuple(t) is t True 我想我需要为此重写\uuuu new\uuu方法,并在\uuuu init\uuu方法中处理这个特殊情况。这有什么食谱吗 当给构造函数一个类实例,它将返回不变时,我宁愿完全跳过\uuuuu init\uuuu,但我看不到任何方法。我还对cls在supe
tuple
所做的那样:
>>> t = (1, 2, 3)
>>> tuple(t) is t
True
我想我需要为此重写\uuuu new\uuu
方法,并在\uuuu init\uuu
方法中处理这个特殊情况。这有什么食谱吗
当给构造函数一个类实例,它将返回不变时,我宁愿完全跳过\uuuuu init\uuuu
,但我看不到任何方法。我还对cls
在super
中的三重用法表示怀疑:
class C:
@staticmethod
def __new__(cls, x=None):
if isinstance(x, cls):
return x
else:
return super(cls, cls).__new__(cls)
def __init__(self, x=None):
if x is self: return # Can I just skip __init__ instead?
self.x = x
(我知道没有参数的super()
,但我不喜欢。)
在学习了更多关于super
和Python中的MRO的知识之后,我发现这段代码并不好。例如,子类化C
会导致
>>> class D(C): pass
>>> d = D(1)
......
RecursionError: maximum recursion depth exceeded while calling a Python object
我非常害怕super()
没有从(词汇或动态?)上下文中神奇地提取参数的参数,因此我决定添加一个“回调”来完成类定义,而不是使用它:
class C2:
@classmethod
def finalise(this_cls_yes_this_one):
@staticmethod
def __new__(cls, x=None):
if isinstance(x, cls):
return x
else:
return super(this_cls_yes_this_one, cls).__new__(cls)
this_cls_yes_this_one.__new__ = __new__
del this_cls_yes_this_one.finalise
def __init__(self, x=None):
if x is self: return
self.x = x
C2.finalise()
您可以使用元类。每当调用实例时,Metacals的
\uuuuuuuuu init\uuuuuuuuuuuuuuuuuuuuu
方法中都会调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。您可以通过重写元类调用函数来处理这两个问题
class MyMetaClass(type):
def __call__(cls, obj, *args, **kwargs):
if (isinstance(obj, cls)):
return obj
else:
self = cls.__new__(cls, obj, *args, **kwargs)
cls.__init__(self, obj, *args, **kwargs)
return self
# Note: In order to be sure that you don't miss anything
# It's better to do super().__call__(obj, *args, **kwargs) here
class A(metaclass=MyMetaClass):
def __init__(self, obj, *args, **kwargs):
self.val = obj
演示:
MyMetaClass的else
子句是否可以是:else:returnsuper()
?是否可以链接到Python的文档,以确认类的\uuuu-cal\uuuuu
中没有其他需要处理的内容?@Alexey我不确定,但为了让Rob放心,你应该使用super()
@Kasramvd-抱歉,我没有仔细阅读这个问题。没关系。考虑到,对于可变值,这可能会产生令人惊讶的结果:<代码> A1. Val= 1;a2=A(a1);a2.val=2;打印(a1.val)代码>类的用户可能期望构造函数为可变对象生成一个副本。这实际上是期望的结果。正如我所说,我希望构造函数返回相同的对象。此外,我的类实例并不是用于变异的。
a = A(10)
b = A(a)
c = A(40)
print(b is a)
print(a.val)
print(b.val)
print(c is a)
print(c.val)
# out:
True
10
10
False
40