在定义类时,在类内部函数属性和数据属性之前加’__’(两个下划线),再和以前一样去访问属性就会报错。
class Student:
__school = '北大'
def __init__(self, name, age):
self.__name = name
self.__age = age
def __run(self):
print('running')
student = Student('小明', 18)
print(Student.__school)
print(Student.__run)
print(student.__name)
# AttributeError: type object 'Student' has no attribute '__school'
发生了什么?我们看下__dict___
print(Student.__dict__)
{'__module__': '__main__', '_Student__school': '北大', '__init__': <function Student.__init__ at 0x0000017BE6766158>, '_Student__run': <function Student.__run at 0x0000017BE67661E0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
发现我们定义的__school和函数__run变成了 ‘_Student__school’, ‘_Student__run’
类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式,其实如果非要访问是可以访问的,
那我们换个方式访问下:
print(Student._Student__school)
# 北大
print(student.__dict__)
# {'_Student__name': '小明', '_Student__age': 18}
print(student._Student__name)
# 小明
这其实是一种变形,变形后,外部无法直接访问,内部可以访问
class Student:
__school = '北大'
def __init__(self, name, age):
self.__name = name
self.__age = age
def __run(self):
print('running')
def walk(self): # 调用run
self.__run()
student = Student('小明', 18)
student.walk()
# running 表示内部直接访问成功。
意义在于保护内部属性数据不被随意访问和更改,可以将数据隐藏起来之后,内部设置一个函数访问属性,添加条件限制,外部访问时调用此函数,必须满足条件限制。
class Student:
__school = '北大'
def __init__(self, name, age):
self.__name = name
self.__age = age
def __run(self):
print('running')
def walk(self):
self.__run()
def tell_info(self):
print('姓名:%s 年龄:%s' %(self.__name, self.__age))
def set_info(self, name, age):
if isinstance(name,str) and isinstance(age, int):
self.__name = name
self.__age = age
else:
print('数据类型错误')
s1 = Student('小明', 18)
s1.tell_info()
# 姓名:小明 年龄:18
s1.tell_info()
# 姓名:小明 年龄:18
s1.set_info('小明', 20)
s1.tell_info()
# 姓名:小明 年龄:20
另外,如果父类不想子类覆盖部分功能,可以利用隐藏将功能私有化:
class A:
def f(self):
print('from A')
def test(self):
self.f()
class B(A):
def f(self):
print('from B')
b = B()
b.test()
from B
class A:
def __f(self): # self._A__f
print('from A')
def test(self):
self.__f() # self._A__f
class B(A):
def __f(self): # self._B__f
print('from B')
b = B()
b.test()
from A