Python是支持面向对象的编程语言,因此它也支持类似纯面向对象语言一样的类访问控制,但是Python没有显式定义诸如private、protecte、public这样的关键字,在Python中,我们主要通过遵循一定的变量、属性和方法命名规约来进行访问控制。
类的第一特性就是封装,为了保护内部代码,大多时候我们不倾向于直接暴露类中定义的代码,而是通过提供的接口进行调用,而为了避免在类的外部直接访问甚至是直接修改类的属性,Python提供了三种方法来控制类属性(包括成员变量和成员方法)的访问。
Python中变量和方法都是默认公有的,此时变量和方法遵循常规的命名规范即可,不需要下划线开头,这样的公有属性可以被子类、类内以及类外访问。
class Person:
def __init__(self, name, age):
self.name = name # 公有变量
self.age = age # 公有变量
def print(self): # 公有方法
return "name: " + self.name
p = Person("zc", 24)
print(p.name) # 查看公有变量
p.print() # 调用公有方法
在Python定义类属性的时候,使用双下划线__
开头的属性,都是私有属性(私有变量和私有方法)。私有属性不能在类的外部被使用或直接访问,只有类对象自己能访问,连子类对象也不能访问到这个数据。
class Person:
def __init__(self, name, age, gender):
self.name = name # 公有变量
self.age = age # 公有变量
self.__gender = gender # 私有变量
def print(self): # 公有方法
return "name: " + self.name
def __look(self): # 私有方法
print(self.name)
print(self.__gender)
p = Person("zc", 24, '男')
print(p.__gender) # 报错AttributeError: 'Person' object has no attribute '__gender',无法访问私有属性
p.print() # 正常输出,类内可以访问私有属性
p.__look() # 报错,AttributeError: 'Person' object has no attribute '__look',无法访问私有属性
上面简单说明了私有属性的设置,但是Python本质上没有严格的私有属性,它其实是将私有属性重命名为_类名__方法名
的格式,因此按照原来的名字访问不到这个属性,但是可以通过形如Person__dict__
从属性列表里看到改名后的结果,并且可以通过改名后的属性名进行访问和修改,就和公有一样。因此,Python的私有属性不具备强制性,可以根据规则绕过限制,只是一种规范。
在Python定义类属性的时候,使用一个下划线_
开头的属性,就是保护属性,只有类实例和子类实例能访问到保护属性。保护属性的访问控制强度没有私有属性那么高,连私有属性都可以通过知晓规则之后绕过访问和修改,保护属性就更不要说限制了。所谓的保护属性更多的是一种编码约定,因为保护属性和普通属性其实是一样,只是我此处用了保护属性,那么你在外部就不要随便访问和修改了。
class Person:
def __init__(self, name, age, gender):
self.name = name # 公有变量
self.age = age # 公有变量
self.__gender = gender # 私有变量
self._phone = 123 # 保护变量
def print(self): # 公有方法
print("name: " + self.name + "gender: " + self.__gender)
def __look(self): # 私有方法
print(self.name)
print(self.__gender)
p = Person("zc", 24, '男')
print(p._phone) # 编码不会报错,但是不建议这样操作