Python 本身就是面向对象的,其中最重要的要素之一是封装,所谓封装就是类中的属性和方法,分为公有和私有,公有可以被外界访问,私有不能被外界访问,这就是封装职工最关键的概念————访问控制。
访问控制有三个级别:公有、私有、受保护
- 私有:只有类自身可以访问
- 受保护:只有类自身和子类可以访问
- 公有:任何类都可以访问
公有(Pubulic)
1 2 3 4 5 6 7 8 9 10
| # 公有Public class Foo(object): bar = 123 def __init__(self, name): self.name = name print(Foo.bar) # 123 foo = Foo('hello') print(foo.name) # hello
|
Foo中的bar属性是类属性,__init__ 中的name是实例的属性,bar和name都是公有属性,外部可以访问
受保护(Procted)
在Python中定义一个受保护的属性,在其名字前面加上_
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| # 受保护(Procted) class Foo(object): _bar = 123 def __init__(self, name): self._name = name class Son(Foo): """ 继承Foo """ def print_name(self): print(self._name) @classmethod def print_bar(cls): """ 类方法 :return: """ print(cls._bar) # print(Foo._bar) # foo = Foo('hello') # print(foo._name) Son.print_bar() # 123 son =Son(456) # 因为是继承,在实例化的时候需要传参数 son.print_name() # 456
|
定义的Son继承自Foo,受保护的对象只能在类的内部和子类中被访问
验证是否能在外部访问
1 2 3
| print(Son._bar) # 123 son = Son(456) print(son._name) # 456
|
实际是可以的,Python用下划线定义受保护的变量,是一种约定规范,而不是语言层面真正实现了访问控制。
私有(Private)
Python定义私有属性,在属性名前加两个下划线__
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Foo(object): __bar = 123 def __init__(self, name): self.__name = name class Son(Foo): """ 继承Foo """ def print_name(self): print(self.__name) @classmethod def print_bar(cls): """ 类方法 :return: """ print(cls.__bar) print(Son.__bar) # ERR son = Son(456) print(son.__name) # ERR
|
深入了解私有属性
Python是如何实现私有属性的:
在Cpython中,会把双下滑线的属性变成_ClassName__ProctedName,不同的Python解释器的处理可能不一致,不作为通用的方法
1 2 3 4
| class Foo(object): __bar = 123 print(Foo._Foo__bar)
|
特例
使用双下滑想线定义私有属性,当属性后也有双下滑线的时候,Python解释器会当做魔术方法,不做私有处理
1 2 3 4
| class Foo(object): __bar__ = 123 print(Foo.__bar__) # 123
|
定义的属性名是__
1 2 3 4
| class Foo(object): __ = 123 print(Foo.__)
|
函数的访问控制
前面主要介绍了属性的访问控制,
在Python中函数是一等公民,所谓一等公民,
就是函数可以像变量一样使用,所以函数的访问控制和属性一样,一样应用上面的规则