问题描述:
类属性访问限制的知识点
第一段代码
class Swan:
'''天鹅类'''
_neck_swan="天鹅的脖子很长" #定义私有属性
def __init__(self):
print("__init__():",Swan._neck_swan) #在实例方法中访问私有属性
swan=Swan() #创建Swan类的实例
print("直接访问:",swan._neck_swan) #保护属性可以通过实例名访问
#输出结果如下。
#__init__(): 天鹅的脖子很长
#直接访问: 天鹅的脖子很长
第一段代码结果:
__init__(): 天鹅的脖子很长
直接访问: 天鹅的脖子很长
第二段代码如下:
class Swan:
'''天鹅类'''
_neck_swan="天鹅的脖子很长" #定义私有属性
def __init__(self):
print("__init__():",Swan._neck_swan) #在实例方法中访问私有属性
swan=Swan() #创建Swan类的实例
print("直接访问:",swan._neck_swan) #保护属性可以通过实例名访问
#输出结果如下。
#__init__(): 天鹅的脖子很长
#直接访问: 天鹅的脖子很长
第二段代码结果如下:
__init__(): 天鹅的脖子很长
加入类名: 天鹅的脖子很长
Traceback (most recent call last):
File "C:/Users/86178/AppData/Local/Programs/Python/Python312/siyoushuxing2.py", line 8, in <module>
print("直接访问:",swan.__neck_swan) #私有属性不能通过实例名访问
AttributeError: 'Swan' object has no attribute '__neck_swan'. Did you mean: '_Swan__neck_swan'?
上述代码的结果总结如下:
访问限制这个知识点,针对类属性的定义。首先,单下划线+属性表示这个属性只能被类本身和实例化对象访问,不能被from module import *访问。其次,双下划线+属性只能被类本身进行访问,不能通过实例化对象访问,如果想通过实例化对象访问,则使用类的实例名._类名__属性名访问。
问题解答:
关于属性访问控制的知识点如下:
-
单下划线
_
:- 单下划线前缀属性(例如
_neck_swan
)是受保护的属性。根据惯例,它表示这个属性不应该被直接访问(虽然技术上还是可以访问的)。 - 它可以通过类本身和实例化对象直接访问,但不建议在外部代码中直接使用。
- 使用
from module import *
时,带有单下划线前缀的属性不会被导入。
- 单下划线前缀属性(例如
-
双下划线
__
:- 双下划线前缀属性(例如
__neck_swan
)是私有的属性。这种属性不能在类的外部直接访问。 - 双下划线前缀会触发名称改写(name mangling),即 Python 会将其改为
_类名__属性名
的形式。 - 只能通过
实例名._类名__属性名
的方式访问。
- 双下划线前缀属性(例如
以下是对比两个代码段的细节解释:
第一段代码:
class Swan:
'''天鹅类'''
_neck_swan = "天鹅的脖子很长" # 定义保护属性
def __init__(self):
print("__init__():", Swan._neck_swan) # 在实例方法中访问保护属性
swan = Swan() # 创建Swan类的实例
print("直接访问:", swan._neck_swan) # 保护属性可以通过实例名访问
输出结果:
__init__(): 天鹅的脖子很长
直接访问: 天鹅的脖子很长
第二段代码:
class Swan:
'''天鹅类'''
__neck_swan = "天鹅的脖子很长" # 定义私有属性
def __init__(self):
print("__init__():", Swan.__neck_swan) # 在实例方法中访问私有属性
swan = Swan() # 创建Swan类的实例
print("直接访问:", swan.__neck_swan) # 私有属性不能通过实例名访问
输出结果:
__init__(): 天鹅的脖子很长
Traceback (most recent call last):
File "C:/Users/86178/AppData/Local/Programs/Python/Python312/siyoushuxing2.py", line 8, in <module>
print("直接访问:", swan.__neck_swan) # 私有属性不能通过实例名访问
AttributeError: 'Swan' object has no attribute '__neck_swan'. Did you mean: '_Swan__neck_swan'?
结论:
- 第一段代码中的
_neck_swan
是保护属性,可以在类内部和通过实例直接访问。 - 第二段代码中的
__neck_swan
是私有属性,通过实例直接访问会导致AttributeError
。如果需要访问,可以使用swan._Swan__neck_swan
。
总结你的理解:
- 保护属性(单下划线):只能被类本身和实例对象访问,不能被
from module import *
导入。 - 私有属性(双下划线):只能被类本身访问,不能通过实例直接访问,如果需要访问,则使用
实例名._类名__属性名
这种改写后的名称访问。