看例子
class A:
# 类变量
b = 1
def __init__(self, x, y):
# 实例变量
self.x = x
self.y = y
# 实例化对象
a = A(2,3)
# 通过实例化对象访问 实例属性
print(a.x, a.y) # 2 3
# 通过实例化对象访问 类属性 向上查找
print(a.b) # 1
# 通过类名访问 类属性
print(A.b) # 1
#通过类名访问 实例属性
print(A.x) # AttributeError: type object 'A' has no attribute 'x'
对于类属性:实例化对象和类都可以访问,是所有实例共享的
实例.类属性 类.类属性
对于实例属性
只能通过实例.实例属性访问类属性,不能通过类.实例属性访问实例属性
属性
1:实例属性:
在__init__(self,…)中初始化
内部调用时都需要加上self.
外部调用时用实例化对象.属性名
2:类属性:
在__init__()外初始化
在内部用类名.类属性名调用
外部既可以用类名.类属性名又可以用实例化对象.类属性名来调用
3:私有属性:
1):单下划线_开头:只是告诉别人这是私有属性,外部依然可以访问更改
2):双下划线__开头:外部不可通过实例化对象.属性名来访问或者更改
实际将其转化为了_类名_属性名,只是在内部将变量名修改了,我们仍让可以通过._类名_属性名访问
类属性的修改
类属性是所有实例共有的属性即静态属性,类似JAVA/C++中static,但是在JAVA中所有类对象共享static内数据的内存,也就是说通过修改static中的值会导致其他对象中static值同样被修改,在Python中并不是这样
通过类修改类属性值(全局修改)
通过实例修改类属性值(局部修改),会在对象中新建一个实例属性a.b存放11
造成以上的原因是因为类和实例存在的位置是独立的,形成了独立的作用域
类属性和实例属性查找顺序
这个例子中a.name的查找顺序是:在实例作用域中找实例属性 —>找不到会向上查找,去类中查找类属性
上面只是简单的例子,那么在多继承情况下又是如何查找的呢??答案是通过MRO(Method Resolution Order)算法
在python2.2之前,python是经典类的继承,python3是新式类继承(object)
深度优先搜索
第一种情况查找没问题,对于第二种情况,先查找了D在查找C,这样的话C中重写的父类中的方法起不到作用,正确的查找应该是A->B->C->D,所以又出现了广度优先搜索算法
但是广度优先搜索在以下情况下又不适用了
如果C、D中有重名的方法,那么B就使用了C中的方法,但是B是继承D的,所以正确的查找顺序应为:A->B->D->C->E
所以在python2.3及以后用的属性搜索算法是C3算法,能够解决以上的问题
通过__mro__显示查找顺序,使用的是python3
例1
例2