python可以创建一个可以用同一类对象的实例初始化的类吗?
我试过了:
class Class():
def __init__(self,**kwargs):
print self
self = kwargs.get('obj',self)
print self
if not hasattr(self,'attr1'):
print 'attr1'
self.attr1 = kwargs.pop('attr1',[])
if not hasattr(self,'attr2'):
print 'attr2'
self.attr2 = kwargs.pop('attr2',[])
print self
self.attr1 = kwargs.pop('attr1',self.attr1)
self.attr2 = kwargs.pop('attr2',self.attr2)
print self.attr1
print self.attr2
如果我创建了一个新实例,就没有问题:
inst = Class(attr1=[1,2,3])
print inst
print inst.attr1,inst.attr2
号
输出为:
attr1
attr2
[1, 2, 3]
[]
[1, 2, 3] []
但如果我用实例inst创建一个新实例:
inst2 = Class(obj=inst)
print inst2
print inst2.attr1,inst2.attr2
。
输出为:
[1, 2, 3]
[]
AttributeError Traceback (most recent call last)
in ()
1 inst2 = Class(obj=inst)
2 print inst2
----> 3 print inst2.attr1,inst2.attr2
AttributeError: Class instance has no attribute 'attr1'
。
我处理这个问题,但我不知道如何解决:
在第一种情况下,实例地址总是相同的("内部"和"外部"类)
在第二种情况下:
"内部"课程:
init调用在新地址创建新实例
然后将self设置为上一个实例并更改地址:确定
self已经有了attr1和atrr2的属性:好的。
但在课堂之外:
inst2有init的地址,没有属性!
怎么了?在Python中,如何处理矫揉造作?这是一种很好的方式吗?
什么?你到底想实现什么?!
想象一下如果你能做到这一点。语法将是什么样的?您将如何向其他人解释如何使用您的代码?
拒绝投票是匿名的,不需要评论(如meta.stackoverflow.com/q/250177/3001761)。更别提你有什么评论了!如果你不能更明确地说,那就不要期待答案。你到底想做什么?通过__init__实现一种奇怪的复制方法?为什么?
什么是"地址矫揉造作"?
@Peterwood此语法将允许第二个实例继承第一个实例的所有属性,但重新初始化的属性除外。
@G.S编辑问题,澄清你想要达到的目标。为什么不使用from_existing_instance类方法,而不是使__init__复杂化呢?
@我说我不能更明确,因为我写了我的整个过程!通过init实现一个奇怪的复制方法?为什么?我在我的问题中说,也许有更好/正确的方式,所以你能解释一下这和复制方法是什么一样的,以及如何做到这一点吗?
@但是你的"整个过程"既不起作用,也没有多大意义。要么给出一个最小限度的可重复的例子,一个散文清晰的解释,或者(最好)两者都给出。也许你想要stackoverflow.com/q/19305296/3001761之类的东西?
我的例子很好,我不会自己写输出!如果这不合理,解释为什么!即使我实现了from_existing_instance方法,我也会遇到同样的问题(除非我剥离了现有实例的所有属性)。我看到了你提出的链接,它与我所做的不一致,因为它使用继承
@Jonrsharpe谢谢你的格式化,你是对的,这个例子不起作用,因为我把object改成了obj
您不必使用继承,我的观点是,在Python中实现备用构造函数的规范方法是使用@classmethod。这感觉像是在和墙争论,所以我不会进一步评论。
@乔恩沙普,我不知道有多少墙可以回答和考虑别人的论点,我只是想清楚你说什么,我回答什么。谢谢你的帮助,我会去看《江户记》的。
不知道你想达到什么样的目标,但从技术上讲,你的错误是:
self = kwargs.get('object',self)
self没有什么魔力,它只是一个函数参数,因此在函数中重新绑定它只会使本地名称self指向函数范围内的另一个对象。它不会影响当前实例(方法包装器传递给__init__的实例),它只是使self成为object的别名。
如果您想要将属性从object复制到self,则必须明确地执行以下操作:
other = kwargs.get('object')
if other is not None:
self.attrx = other.attrx
self.attry = other.attry
# etc
号
哦,是的:Python是高级语言,没有什么比"地址矫揉造作"更像的了——您所拥有的只是引用对象的名称(实际上,名称=>对象映射)。名称只是一个名称,而对象实际生活的地方并不是您关心的问题。
所以,如果我理解的很好,self-it只是局部变量,它是当前实例的别名(通过方法包装器传递给init)?那么,如果我重新绑定它,我会"丢失"init范围内的当前实例吗?@布鲁诺人
@布鲁诺·德斯惠利埃
@g.s您想阅读nedbatchelder.com/text/names.html
谢谢@brunodesthuilliers
感谢以上评论,我了解两件事:
self只是一个局部变量,而不是类实例
_init_是一个类内置方法,用于从其他对象初始化实例。
因此,如果我想从现有实例初始化一个新的类实例,我只需要创建一个"initializer"方法来调用_init_:
class Class():
def __init__(self,**kwargs):
self.attr1 = kwargs.pop('attr1',[])
self.attr2 = kwargs.pop('attr2',[])
def Class(self,**kwargs):
return Class(attr1 = kwargs.pop('attr1',self.attr1),\
attr2 = kwargs.pop('attr2',self.attr2))
像这样使用:
inst = Class(attr1=[1,2,3])
print inst
print inst.attr1,inst.attr2
。
输出:
[1, 2, 3] []
inst2 = inst.Class(attr2=[12,11])
print inst2
print inst2.attr1,inst2.attr2
。
输出:
[1, 2, 3] [12, 11]
。
"self只是一个局部变量,而不是类实例":self是函数作用域中的一个名称,这个名称最初是指当前实例(调用方法的实例)。