Python的类变量引用

文章目录


记一下对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里存的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值