python中并没有类似其他面向对象语言的private和public属性,无法在语言层面上用语言特性去封装数据。python用过对属性和方法的命名约定来实现数据封装的。
- 约定单划线_开头的属性和方法属于类的私有成员(仅仅只是一个约定,并不会真的阻止用户去访问这个属性或方法)
- 双划线__开头的函数如(__init__)等会导致访问名称变成其他形式(如类A有一个__private()方法,则访问时它的名称会变为_A__private)
注:双划线__主要目的是为了将某个属性在子类中隐藏起来
举个例子,我们定义了class A。
class A():
def __init__(self,xing,gender):
self.namea="aaa"
self.xing = xing
self.__gender = gender
def funca(self):
print("function a : {}".format(self.namea))
a = A('wang','boy')
print(a.namea) #[OUT]: aaa
print(a.xing) #[OUT]: wang
print(a.__gender) #[OUT]: 'A' object has no attribute '__gender'
我们通过a.name和a.xing可以正确地访问到A的属性,但是通过a.__gender时就报错A没有__gender属性,可是我们明明定义了__gender属性啊。根据约定2,双下划线开头的属性和方法的访问名称会变成其他形式,因此我们用
print(a._A__gender) #[OUT] : boy
成功的访问到了__gender属性。
总结:
使用双下划线开始会导致访问名称变成其他形式。 比如,在前面的类A中,私有属性会被分别重命名为 _A__private
和 _A__private_method
。 这时候你可能会问这样重命名的目的是什么,答案就是继承——这种属性通过继承是无法被覆盖的。