记一下对python变量的理解。
查看如下代码
class TestObj(object):
pass
class Child(object):
properties = {}
move_duration = TestObj()
test = move_duration
def __init__(self):
super(Child, self).__init__()
self.bb = self.move_duration
print 'set bb:%s'%self.bb
if __name__ == "__main__":
myTest = Child()
print "move_duration", id(myTest.move_duration)
print "test", id(myTest.test)
print "test bb", id(myTest.bb)
print "after set move_duration to 999"
setattr(myTest, 'move_duration', 999)
print "move_duration", id(myTest.move_duration)
print "test", id(myTest.test)
print "test bb", id(myTest.bb)
pass
结果
set bb:<__main__.TestObj object at 0x0000000003357898>
move_duration 53835928
test 53835928
test bb 53835928
after set move_duration to 999
move_duration 52943616
test 53835928
test bb 53835928
一开始结构如下:
执行 setattr(myTest, ‘move_duration’, 999)后变为:
即我们看到的结果。
PS:setattr(myTest, ‘move_duration’, 999)修改的实例myTest的类变量,之后new出来的Child(),其move_duration的地址还是53835928
查看如下代码
import traceback
class NodePorperty(object):
def __init__(self, name, ptype, title, desc, default=0):
self.name = name
if type(ptype) is type:
self.type = ptype
elif type(ptype) is tuple:
self.type, self.subtype = ptype
else:
raise TypeError, 'Invalid %s type: %s'% (self.__class__.__name__, type)
self.title = title
self.description = desc
self.default = self.type(default)
def __get__(self, instance, cls=None):
# print "getName,:%s, \nstack:%s\n"%(self.name, traceback.extract_stack())
return instance.properties.get( self.name, self.default )
def __set__(self, instance, value):
# print "set:%s to %s \n %s\n"%(self.name, value,traceback.extract_stack())
instance.properties[self.name] = self.type(value)
def __delete__(self, instance):
del instance.properties[self.name]
class Child(object):
properties = {}
move_duration = NodePorperty('move_duration', float, 'move_duration', 'abc', 0.2)
test = move_duration
def __init__(self):
super(Child, self).__init__()
self.bb = self.move_duration
# print 'set bb:%s'%self.bb
if __name__ == "__main__":
myTest = Child()
print "move_duration", id(myTest.move_duration)
print "test", id(myTest.test)
print "test bb", id(myTest.bb)
print "after set move_duration to 999"
setattr(myTest, 'move_duration', 999)
print "move_duration", id(myTest.move_duration)
print "test", id(myTest.test)
print "test bb", id(myTest.bb)
pass
结果
move_duration 54286552
test 54286552
test bb 54286552
after set move_duration to 999
move_duration 54286528
test 54286528
test bb 54286552
NodePorperty重写了__get__, __set__方法。
修改了move_duration会同时修改myTest的test值。但是并没有修改myTest.bb的值!
如果把日志打开,结果如下:
getName,:move_duration,
stack:[('D:/codelife/leetcode_python/test/NodeTest.py', 40, '<module>', 'myTest = Child()'), ('D:/codelife/leetcode_python/test/NodeTest.py', 35, '__init__', 'self.bb = self.move_duration'), ('D:/codelife/leetcode_python/test/NodeTest.py', 18, '__get__', 'print "getName,:%s, \\nstack:%s\\n"%(self.name, traceback.extract_stack())')]
set bb:0.2
move_duration getName,:move_duration,
stack:[('D:/codelife/leetcode_python/test/NodeTest.py', 41, '<module>', 'print "move_duration", id(myTest.move_duration)'), ('D:/codelife/leetcode_python/test/NodeTest.py', 18, '__get__', 'print "getName,:%s, \\nstack:%s\\n"%(self.name, traceback.extract_stack())')]
55793880
test getName,:move_duration,
stack:[('D:/codelife/leetcode_python/test/NodeTest.py', 42, '<module>', 'print "test", id(myTest.test)'), ('D:/codelife/leetcode_python/test/NodeTest.py', 18, '__get__', 'print "getName,:%s, \\nstack:%s\\n"%(self.name, traceback.extract_stack())')]
55793880
test bb 55793880
after set move_duration to 999
set:move_duration to 999
[('D:/codelife/leetcode_python/test/NodeTest.py', 45, '<module>', "setattr(myTest, 'move_duration', 999)"), ('D:/codelife/leetcode_python/test/NodeTest.py', 22, '__set__', 'print "set:%s to %s \\n %s\\n"%(self.name, value,traceback.extract_stack())')]
move_duration getName,:move_duration,
stack:[('D:/codelife/leetcode_python/test/NodeTest.py', 46, '<module>', 'print "move_duration", id(myTest.move_duration)'), ('D:/codelife/leetcode_python/test/NodeTest.py', 18, '__get__', 'print "getName,:%s, \\nstack:%s\\n"%(self.name, traceback.extract_stack())')]
55793808
test getName,:move_duration,
stack:[('D:/codelife/leetcode_python/test/NodeTest.py', 47, '<module>', 'print "test", id(myTest.test)'), ('D:/codelife/leetcode_python/test/NodeTest.py', 18, '__get__', 'print "getName,:%s, \\nstack:%s\\n"%(self.name, traceback.extract_stack())')]
55793808
test bb 55793880
原因很简单,因为重写了__get__,__set__
一开始结构是:
执行 setattr(myTest, ‘move_duration’, 999)后变为:
为什么myTest.bb指向的是float 0.2.因为self.move_duration,返回的是float。
setattr(myTest, ‘move_duration’, 999),修改的对象NodeProperty里存的值。