python类属性、实例属性、私有属性、保护属性

python类属性与实例属性

定义

class A:
    class_name = "calss" # 类属性
    def __init__(self):
        self.object_name = "object" # 实例属性

if __name__ == "__main__":
    print(A.class_name) # 正确,类名可以访问类属性
    # print(A.object_name) # 错误,类名不可以访问实例属性
    a = A()
    print(a.object_name) # 正确,实例名可以访问实例属性
    print(a.class_name) # 正确,如果实例中没有和类属性同名的实例属性,则类属性会为实例提供默认值,此时实例名能访问类属性
    a.class_name = "I am a" # 通过实例属性无法更改类属性的值
    print(A.class_name, a.class_name)

输出:

calss
object
calss
calss I am a
  • class_name是类属性,写在__init__方法之外,属于类,不断实例化了多少个实例,类属性在内存中始终只有一份。
  • object_name是实例属性,写在__init__方法内,self是实例本身的引用。

类属性为实例属性提供默认值

如上例子,当用实例a来访问属性a.class_name时:

  • 如果a有class_name这个实例属性,则直接访问。
  • 如果a没有的话,则通过实例a访问到了类属性class_name,即类属性为实例属性提供默认值。

实例属性覆盖类属性

当实例属性与类属性重名时,通过实例访问时实例属性会覆盖类属性,由于python中属性是可以动态添加的,如上例子中,本来没有实例属性class_name,但是通过实例a动态添加了一个实例属性class_name,那么下次再通过实例a访问class_name时访问到的就是实例属性,而不是类属性了。

修改类属性

  • 通过实例修改类属性的话,实际上会新添加一个新的实例属性,原先类属性是不会变的。
  • 首先当然可以通过类名修改类属性。
     A.class_name = "I am A"
     print(A.class_name)
    
  • 但是一般用一个更python风格的方法。对于公开的类属性,是会被子类继承的,因此可以通过创建子类专门定制类属性。
    class B(A):
      class_name = "new class"
    

python私有属性与保护属性

  • python中类属性和实例属性都可以定义为私有的,只需要在属性名前加两个下划线即可,这样在外接直接访问的话会失败,但是如果在属性名前再加一个下划线和类名,则在外界依然可以访问,因为python中不存在真正的私有属性,只是解释器见到两个下划线开头的属性会给它改个名字。
    class A:
        __class_name = "calss" # 类属性
        def __init__(self):
            self.__object_name = "object" # 实例属性
    
    
    
    if __name__ == "__main__":
       a = A()
    #    print(A.__class_name) # 错误,私有类属性不能在类外访问
    #    print(a.__object_name) # 错误,私有实例属性不能在外部访问
       print(A._A__class_name) # 正确
       print(a._A__object_name) # 正确
      
    
posted @ 2022-03-10 10:44  肖肖凯  阅读(510)  评论(0)    收藏  举报