问题
Can python create a class that can be initialised with an instance of the same class object?
I've tried this:
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
If I create a new instance there is no problem:
inst = Class(attr1=[1,2,3])
print inst
print inst.attr1,inst.attr2
The output is:
<__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] []
But if I create a new instance with the instance inst
:
inst2 = Class(obj=inst)
print inst2
print inst2.attr1,inst2.attr2
The output is:
<__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'
I handle the problem but i dont know how to solve it:
- in the 1st case the instance address is always the same ("inside" and "outside" the class)
in the 2nd case:
- "inside" the class:
- the init call create a new instance at a new address
- then self is set to the previous instance and change address: OK
self
already has attributesattr1
andatrr2
: OKbut "outside" the class:
inst2
has the address from the init and has no attributes!
What is wrong ? How does address affectation work in Python? Is it a good manner of doing this?
回答1:
Not sure what you're trying to achieve, but technically your error is here:
self = kwargs.get('object',self)
There's nothing magic with self
, it's just a function argument, and as such a local variable, so rebinding it within the function will only make the local name self
points to another object within the function's scope. It's in no way affecting the current instance (the one that was passed to __init__
by the method wrapper), it just makes self
an alias for object
.
If what you want is to copy attributes from object
to self
, you have to do it explicitly:
other = kwargs.get('object')
if other is not None:
self.attrx = other.attrx
self.attry = other.attry
# etc
Oh and yes: Python is high-level language, there's nothing like "address affectation" - all you have are names refering to objects (really, name=>object mapping). A name is just a name, and where the object actually lives is none of your concerns.
回答2:
Thanks to the comments above I understand 2 things:
self
is just a local variable and it s not the class instance_init_
it s an class built-in method for initialize the instance from other object
So if I want to be able to initialize a new class instance from an existing instance, I have just to create an "initializer" method which call the
_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))
And use it like this:
inst = Class(attr1=[1,2,3])
print inst
print inst.attr1,inst.attr2
Output:
<__main__.Class instance at 0x7eff842d5368>
[1, 2, 3] []
inst2 = inst.Class(attr2=[12,11])
print inst2
print inst2.attr1,inst2.attr2
Output:
<__main__.Class instance at 0x7eff842d56c8>
[1, 2, 3] [12, 11]
来源:https://stackoverflow.com/questions/33127950/class-constructor-able-to-init-with-an-instance-of-the-same-class-object