Class 构造函数能够使用同一 class 对象的实例进行初始化
Class constructor able to init with an instance of the same class object
可以 python 创建一个 class 可以用同一个 class 对象的实例初始化吗?
我试过这个:
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
输出为:
<__main__.Class instance at 0x7f2025834cf8>
<__main__.Class instance at 0x7f2025834cf8>
attr1
attr2
<__main__.Class instance at 0x7f2025834cf8>
[1, 2, 3]
[]
<__main__.Class instance at 0x7f2025834cf8>
[1, 2, 3] []
但是如果我用实例 inst
:
创建一个新实例
inst2 = Class(obj=inst)
print inst2
print inst2.attr1,inst2.attr2
输出为:
<__main__.Class instance at 0x7f202584b7e8>
<__main__.Class instance at 0x7f2025835830>
<__main__.Class instance at 0x7f2025835830>
[1, 2, 3]
[]
<__main__.Class instance at 0x7f202584b7e8>
AttributeError Traceback (most recent call last)
<ipython-input-228-29c9869a9f4d> in <module>()
1 inst2 = Class(obj=inst)
2 print inst2
----> 3 print inst2.attr1,inst2.attr2
AttributeError: Class instance has no attribute 'attr1'
我处理了这个问题,但我不知道如何解决:
- 在第一种情况下,实例地址始终相同("inside" 和 "outside" class)
第二种情况:
- "inside" class:
- init 调用在新地址创建一个新实例
- 然后将自己设置为之前的实例并更改地址:OK
self
已经有属性 attr1
和 atrr2
: OK
但是"outside" class:
inst2
有来自 init 的地址,没有属性!
怎么了? Python 中的地址伪装是如何工作的?
这是一种很好的做法吗?
不确定您要实现的目标,但从技术上讲,您的错误在于:
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 是高级语言,没有什么比 "address affectation" - 你所拥有的只是引用对象的名称(真的,名称=>对象映射)。名称只是名称,对象实际所在的位置是您关心的none。
感谢上面的评论,我明白了两件事:
self
只是一个局部变量,它不是 class 实例
_init_
它是一个 class 用于从其他对象 初始化实例的内置方法
因此,如果我希望能够从现有实例初始化一个新的 class 实例,我只需创建一个 "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
输出:
<__main__.Class instance at 0x7eff842d5368>
[1, 2, 3] []
inst2 = inst.Class(attr2=[12,11])
print inst2
print inst2.attr1,inst2.attr2
输出:
<__main__.Class instance at 0x7eff842d56c8>
[1, 2, 3] [12, 11]
可以 python 创建一个 class 可以用同一个 class 对象的实例初始化吗?
我试过这个:
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
输出为:
<__main__.Class instance at 0x7f2025834cf8>
<__main__.Class instance at 0x7f2025834cf8>
attr1
attr2
<__main__.Class instance at 0x7f2025834cf8>
[1, 2, 3]
[]
<__main__.Class instance at 0x7f2025834cf8>
[1, 2, 3] []
但是如果我用实例 inst
:
inst2 = Class(obj=inst)
print inst2
print inst2.attr1,inst2.attr2
输出为:
<__main__.Class instance at 0x7f202584b7e8>
<__main__.Class instance at 0x7f2025835830>
<__main__.Class instance at 0x7f2025835830>
[1, 2, 3]
[]
<__main__.Class instance at 0x7f202584b7e8>
AttributeError Traceback (most recent call last)
<ipython-input-228-29c9869a9f4d> in <module>()
1 inst2 = Class(obj=inst)
2 print inst2
----> 3 print inst2.attr1,inst2.attr2
AttributeError: Class instance has no attribute 'attr1'
我处理了这个问题,但我不知道如何解决:
- 在第一种情况下,实例地址始终相同("inside" 和 "outside" class)
第二种情况:
- "inside" class:
- init 调用在新地址创建一个新实例
- 然后将自己设置为之前的实例并更改地址:OK
self
已经有属性attr1
和atrr2
: OK但是"outside" class:
inst2
有来自 init 的地址,没有属性!
怎么了? Python 中的地址伪装是如何工作的? 这是一种很好的做法吗?
不确定您要实现的目标,但从技术上讲,您的错误在于:
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 是高级语言,没有什么比 "address affectation" - 你所拥有的只是引用对象的名称(真的,名称=>对象映射)。名称只是名称,对象实际所在的位置是您关心的none。
感谢上面的评论,我明白了两件事:
self
只是一个局部变量,它不是 class 实例_init_
它是一个 class 用于从其他对象 初始化实例的内置方法
因此,如果我希望能够从现有实例初始化一个新的 class 实例,我只需创建一个 "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
输出:
<__main__.Class instance at 0x7eff842d5368>
[1, 2, 3] []
inst2 = inst.Class(attr2=[12,11])
print inst2
print inst2.attr1,inst2.attr2
输出:
<__main__.Class instance at 0x7eff842d56c8>
[1, 2, 3] [12, 11]