Python类中的名字查找有好几个点,常见俊龙金马的有关文章
class MyClass:
cls_attr=0
cls_attrB=0
def __init__(self,val1):
self.attr=val1
#cls_attr+=1 #UnboundLocalError: local variable 'cls_attr'
#referenced before assignment
'''1、实例方法内不可直接访问类属性,既便访问实例属性
都要用self.attr,要访问类属性应该也用self.cls_attr
,按照实例属性的查找顺序,在实例属性中没找到时到
类属性中查找,但修改类属性时实际上是将修改后的值
存放到增加的与类属性同名的实例属性中,从而屏蔽保护
了类属性。或者直接"类对象.类属性",这样就会直接
修改到类属性了。
2、函数与类都会生成作用域,除了内嵌作用域Builtins
与全局作用域Global,也只有函数与类会生成嵌套作用域
与局部作用域Enclosed与Local,形成LEGB的作用域查找
顺序,但类定义中的方法不可以看作是函数,如果方法
可以看作函数,那此处直接按名访问"嵌套作用域"的类
属性就是可以的,但实际上不是,因为既便是类方法也
不能直接按名访问类属性,而是使用类对象引用cls访问
类属性,使用类对象的属性查找规则
'''
self.cls_attr+=1
'''3、通过实例引用类属性的方式,"self.cls_attr"
实例一旦修改类属性,会立即为实例增加一个与类属性
同名的实例属性保存修改后的值,而不会影响类属性,
类属性本就是给类、全体实例访问的,这样做到实例
属性屏蔽从而保护类属性
'''
MyClass.cls_attrB+=1
'''4、直接在实例方法内使用"类对象.类属性"的方式,
修改类属性是直接影响的类属性
'''
def get_cls_attr(self):
return self.cls_attr
'''实例当然能访问类属性,实例属性的查找顺序有好几个点'''
@classmethod
def get_cls_attrc(cls):
return cls.cls_attr
@classmethod
def set_cls_attr(cls,val):
cls.cls_attr=val
'''5、或者在类方法内使用"类对象引用类属性"修改类属性本身
'''
obj=MyClass(1) #类属性cls_attr仍然是0,增加实例属性cls_attr=1
obj2=MyClass(1) #类属性cls_attr仍然是0,增加实例属性cls_attr=1
print(obj.get_cls_attr()) #1
print(obj2.get_cls_attr()) #1
print(MyClass.get_cls_attrc()) #0,被obj.cls_attr与obj2.cls_attr屏蔽保护了
print(MyClass.cls_attrB) #2 使用"类对象.类属性"修改类属性将影响本身
MyClass.set_cls_attr(9)
print(MyClass.get_cls_attrc()) #9