from weakref import WeakKeyDictionary
class Score():
""" score should in [0,100] """
def __init__(self):
self.score = WeakKeyDictionary()
#self.score = {}
def __get__(self, instance, owner):
return self.score[instance]
def __set__(self, instance, value):
if 0 <= value <= 100:
self.score[instance] = value
else:
raise ValueError("score not in [0,100]")
class Student():
print("aaaaaaaaa")
# 托管属性定义在类级别上
score1 = Score()
score2 = Score()
score3 = Score()
def __init__(self, stuid, name, score1, score2, score3):
self.stuid = stuid
self.name = name
self.score1 = score1
self.score2 = score2
self.score3 = score3
def returnMe(self):
return "%s, %s, %i, %i, %i" % (
self.stuid,
self.name,
self.score1,
self.score2,
self.score3)
stu = Student("20101120", "malong", 67, 77, 88)
print(stu.returnMe())
这段代码最终编译后就是生成一堆代码对象,首先是模块对象
具体过程可以这样理解:
模块级代码对象:整个模块首先会被编译为一个顶层代码对象,包含模块中所有代码的编译信息(包括类定义、函数定义、全局变量等)。
类与函数的代码对象:
每个类(Score、Student)的定义会生成对应的类代码对象
类中的每个方法(init、get、set、returnMe)会各自生成独立的函数代码对象
类体中执行的代码(如 print("aaaaaaaaa"))也会包含在类的代码对象中
代码对象的层级关系:
模块代码对象包含类定义的代码对象
类代码对象包含其内部方法的代码对象
所有这些代码对象共同构成了程序的编译后表示
当你运行这个脚本时,Python 解释器会:
首先将整个模块编译为代码对象
执行模块代码对象中的字节码指令co_code,依次创建类和函数对象
类和函数对象会引用它们对应的代码对象(通过 code 属性)
最后执行模块级的代码(如创建 stu 实例并打印结果)
通过dis.dis(代码对象.co_code)和dis.dis(代码对象)可以看到指令是一样的,但是dis.dis(代码对象)还包含指令所需的元数据信息(如常量表)
单独看 co_code 很难直接理解,通常需要结合代码对象的其他属性:
co_varnames:局部变量名列表
co_consts:常量列表
co_names:全局变量 / 属性名列表