类变量 实例变量 属性查找顺序

看例子

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
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/f1ngf1ngy1ng/article/details/80559777