Python3之类和实例访问限制
在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。
但是,从前面的Student类定义来看,外部代码还是可以自由地修改一个实例的name,score属性
1 2 3 4 5 | >>> bart.score 59 >>> bart.score = 99 >>> bart.score 99 |
如果要让内部属性不被外部访问,可以把属性的名称前面加上两个下划线__,在python中,实例的变量名如果以__开头,就变成了私有变量(private),只有内部可以访问,外部不能访问
1 2 3 4 5 6 7 8 9 10 11 12 | >>> class Student( object ): ... def __init__( self ,name,score): ... self .__name = name ... self .__score = score ... def print_score( self ): ... print ( '%s:%s' % ( self .__name, self .__score)) ... >>> bart = Student( 'Zhangsan' , 59 ) >>> bart.__name Traceback (most recent call last): File "<stdin>" , line 1 , in <module> AttributeError: 'Student' object has no attribute '__name' |
这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的包含,代码更加健壮
如果外部代码想要获取name和score怎么办?可以给类Student增加get_name和get_score方法
1 2 3 4 5 6 7 8 9 10 | class Student( object ): def __init__( self ,name,score): self .__name = name self .__score = score def print_score( self ): print ( '%s:%s' % ( self .__name, self .__score)) def get_name( self ): return self .__name def get_score( self ): return self .__score |
通过bart.get_name()即可返回对应name
如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法
1 2 3 4 5 6 7 8 9 10 11 12 | class Student( object ): def __init__( self ,name,score): self .__name = name self .__score = score def print_score( self ): print ( '%s:%s' % ( self .__name, self .__score)) def get_name( self ): return self .__name def get_score( self ): return self .__score def set_score( self ,score): self .__score = score |
set_score除了self还包含一个参数score修改方法为
1 | bart.set_score( 99 ) |
原先直接通过bart.score=99也可以直接修改,为什么要定义一个方法大费周折?因为在方法中,可以对参数进行检查,避免传入无效的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Student( object ): def __init__( self ,name,score): self .__name = name self .__score = score def print_score( self ): print ( '%s:%s' % ( self .__name, self .__score)) def get_name( self ): return self .__name def get_score( self ): return self .__score def set_score( self ,score): if 0 < = score< = 100 : self .__score = score else : raise ValueError( 'bad score' ) |
如果传递了无效的成绩会报错
1 2 3 4 5 6 | Traceback (most recent call last): File "Student.py" , line 28 , in <module> bart.set_score( 101 ) File "Student.py" , line 15 , in set_score raise ValueError( 'bad score' ) ValueError: bad score |
注意,在python中,变量名类似__xxx___,也就是以双下划线开头并且以双下划线结尾的是特殊变量,特殊变量是可以直接访问的,不是private变量,所以不能用__name__,__score__这样的变量名。
有些时候,你会看到以一个下划线开头的实例变量名,比如_name
,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name
是因为Python解释器对外把__name
变量改成了_Student__name
,所以,仍然可以通过_Student__name
来访问__name
变量:
1 2 | >>> bart._Student__name 'Zhangsan' |
但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name
改成不同的变量名。
注意下面这种错误写法
1 2 3 4 5 6 | >>> bart = Student( 'Zhangsan' , 59 ) >>> bart.get_name() 'Zhangsan' >>> bart.__name = 'Lisi' >>> bart.__name 'Lisi' |
表面上看,外部代码“成功”地设置了__name
变量,但实际上这个__name
变量和class内部的__name
变量不是一个变量!内部的__name
变量已经被Python解释器自动改成了_Student__name
,而外部代码给bart
新增了一个__name
变量。不信试试:还是原来的Zhangsan
1 2 | >>> bart.get_name() 'Zhangsan' |
练习:
1 2 3 4 | class Student( object ): def __init__( self , name, gender): self .name = name self .gender = gender |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Student( object ): def __init__( self ,name,gender): self .__name = name self .__gender = gender def get_gender( self ): return self .__gender def set_gender( self ,gender): if gender = = 'male' or gender = = 'female' : self .__gender = gender else : raise ValueError( 'bad gender性别为male或者female' ) bart = Student( 'Zhangsan' , 'male' ) print (bart.get_gender()) bart.set_gender( 'femalde' ) print (bart.get_gender()) |
如果传递的性别参数不是male或者female则报错
1 2 3 4 5 6 | Traceback (most recent call last): File "Student2.py" , line 14 , in <module> bart.set_gender( 'femalde' ) File "Student2.py" , line 11 , in set_gender raise ValueError( 'bad gender性别为male或者female' ) ValueError: bad gender性别为male或者female |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!