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'  

我处理了这个问题,但我不知道如何解决:

怎么了? 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]