变量名的定义有五种常见的定义形式:
- xx:公有变量
- _xx:单前置下划线,称为保护变量,不能通过from XXX import xxx导入,只有类对象和子类对象能访问到这个数据。_xx 实现了模块级别的私有化。
- __xx: 双前置下划线,用于声明变量或者方法私有,无法在外部直接访问,只能在类的内部调用。
- __xx__ :双前后下划线,系统定义名字,例如:_init_,不要自己定义这样格式的变量名字。
- xx_: 单后置下划线,用于避免与Python关键词的冲突
我们一起来看一个例子:
class Person(object):
def __init__(self, name, age, taste):
self.name = name
self._age = age
self.__taste = taste
def showperson(self):
print(self.name)
print(self._age)
print(self.__taste)
def dowork(self):
self._work()
self.__away()
def _work(self):
print('my _work')
def __away(self):
print('my __away')
class Student(Person):
def construction(self, name, age, taste):
self.name = name
self._age = age
self.__taste = taste
def showstudent(self):
print(self.name)
print(self._age)
print(self.__taste)
@staticmethod
def testbug():
_Bug.showbug()
# 模块内可以访问,当from cur_module import *时,不导入
class _Bug(object):
@staticmethod
def showbug():
print("showbug")
s1 = Student('jack', 25, 'football')
s1.showperson()
print('*'*20)
"""
上面三行代码的输出结果:
jack
25
football
********************
"""
# s1.showstudent()
"""
上述代码执行结果:
AttributeError: 'Student' object has no attribute '_Student__taste'
原因是__taste是私有属性,导致访问错误。
"""
s1.construction('rose', 30, 'basketball')
s1.showperson()
print('*'*20)
"""
上述三行代码执行的结果为:
rose
30
football
********************
"""
s1.showstudent()
print('*'*20)
"""
上述两行代码的输出结果:
rose
30
basketball
********************
"""
Student.testbug()
"""
上述代码的执行结果:
showbug
"""
s1._work()
s1.__away() # __away()是一个私有方法
"""
上面两行代码的输出为:
my _work
Traceback (most recent call last):
File "exercise.py", line 60, in <module>
s1.__away()
AttributeError: 'Student' object has no attribute '__away'
"""
总结
- 父类中属性和方法名为 __名字 的,子类不继承,子类也不访问。
- 如果在子类中向 __名字 赋值,那么会在子类中定义的一个与父类相同名字的属性,例如:Student类中的 construction方法。
- _名字 的变量、函数、类在使用from xxx import * 时都不会被导入。