MvG*_*MvG 3 python constructor casting python-3.x
我正在写一个自定义类型Foo
,我想实现以下目标:写作时
foo = Foo(bar)
Run Code Online (Sandbox Code Playgroud)
那么如果bar
已经是一个实例Foo
,则Foo(foo)
返回该对象未修改,所以foo
并bar
引用同一个对象.否则,Foo
应使用来自bar
任何Foo.__init__
认为合适的方式的信息创建类型的新对象.
我怎样才能做到这一点?
我认为这Foo.__new__
是关键.Foo.__new__
如果instanceof
检查成功则返回现有对象应该相当容易,super().__new__
否则调用.但是文档__new__
写这个:
如果
__new__()
返回cls的实例,则将__init__()
调用新实例的方法__init__(self[, ...])
,其中self是新实例,其余参数与传递给的相同__new__()
.
在这种情况下,我将返回所请求类的实例,尽管不是新实例.我可以以某种方式阻止呼叫__init__
吗?或者我是否必须在内部添加一个检查__init__
来检测是为新创建的实例还是为现有实例调用它?后者听起来像代码重复,应该是可以避免的.
恕我直言,你应该直接使用__new__
和__init__
.在init中进行的测试,看看你是应该初始化一个新对象还是已经有一个现有对象,这样就很简单,没有代码重复,增加的复杂性是恕我直言
class Foo:
def __new__(cls, obj):
if isinstance(obj, cls):
print("New: same object")
return obj
else:
print("New: create object")
return super(Foo, cls).__new__(cls)
def __init__(self, obj):
if self is obj:
print("init: same object")
else:
print("init: brand new object from ", obj)
# do the actual initialization
Run Code Online (Sandbox Code Playgroud)
它按预期给出:
>>> foo = Foo("x")
New: create object
init: brand new object from x
>>> bar = Foo(foo)
New: same object
init: same object
>>> bar is foo
True
Run Code Online (Sandbox Code Playgroud)