我所要求的可能在Python中是不可能的,可能源于我习惯于指针,但这就是它如何:在python中可以实现以下目标吗?
class A(object):
#body of class
a = A() #create a new object
b = A(a) #"b" is now an alias for "a"
我天真地尝试这样做是
class A(object):
def __init__(self, x):
if isinstance(x, A):
self = x
但是,当然,这是无意义的,因为自我只是一个局部变量。
编辑:要清楚,这不是简单的变量赋值(即b=a
创建别名但我不在乎)。当我试图构建一个包含大量相同类型对象的循环时,出现了这个问题:
class A(object):
#blah
l = []
for cond in conditions:
tmp = A(*cond)
l.append(tmp)
如果cond[0]
是A类型的另一个对象,则tmp
只是对该对象的引用。
现在,有一个解决方法,但这不是我要求的。我想知道我的原始问题是否有解决方案。
答案 0 :(得分:2)
如果你想这样做,必须在对象__new__
方法中进行。您可以在其中影响新对象的创建,而不是在创建后修改它们的__init__
。一种方法是
class A:
def __new__(cls, copy=None):
if copy: # This assumes that instances of A cannot be falsy
if isinstance(copy, A):
return copy
else:
raise ValueError("Argument not of type A")
else:
return super().__new__(cls)
a = A()
b = A(a)
b is a # True
答案 1 :(得分:2)
您可以使用__new__
:
class A(object):
def __new__(cls, param=None):
if isinstance(param, A):
return param
return super().__new__(cls)
def __init__(self, param=None): # should match __new__ signature
if isinstance(param, A):
return
self.param = param
# normal initialization
据说你可能想重新考虑你的架构。
答案 2 :(得分:0)
我认为最好的方法实际上是在这里使用元类,特别是如果你计划使用继承,尽管,元类确实增加了一些复杂性。如果只是,我会呼吁这是创建单例类的常用方法,这与你原则上做的非常相似。但这是一个草图:
In [43]: class MyMeta(type):
...: def __call__(cls, *args, **kwargs):
...: if isinstance(args[0], cls):
...: return args[0]
...: else:
...: return super(MyMeta, cls).__call__(*args, **kwargs)
...:
In [44]: class A(metaclass=MyMeta):
...: def __init__(self, arg1, arg2):
...: print("initialized")
...:
In [45]: a1 = A(1, 1)
initialized
In [46]: a2 = A(2, 2)
initialized
In [47]: a3 = A(a1, 3)
In [48]: [hex(id(x)) for x in (a1, a2, a3)]
Out[48]: ['0x103ccd160', '0x103ccd198', '0x103ccd160']
In [49]: a1 is a2, a1 is a3
Out[49]: (False, True)
注意,来自docs
__new__()
主要用于允许不可变类型的子类 (例如int
,str
或tuple
)来自定义实例创建。它是 也经常在自定义元类中重写以便自定义 课堂创作。
另请注意,使用此方法时,不会再次调用__init__
,可能是您想要的。
In [53]: class A(object):
...: def __new__(cls, *args, **kwargs):
...: if isinstance(args[0], A):
...: return args[0]
...: return super().__new__(cls)
...:
...: def __init__(self, arg1, arg2): # should match __new__ signature
...: print("initialized")
...:
In [54]: a1 = A(1, 1)
initialized
In [55]: a2 = A(2, 2)
initialized
In [56]: a3 = A(a1, 3)
initialized
In [57]: a1 is a2, a1 is a3
Out[57]: (False, True)