Python3之类和实例访问限制
在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。
但是,从前面的Student类定义来看,外部代码还是可以自由地修改一个实例的name,score属性
>>> bart.score
59
>>> bart.score=99
>>> bart.score
99
如果要让内部属性不被外部访问,可以把属性的名称前面加上两个下划线__,在python中,实例的变量名如果以__开头,就变成了私有变量(private),只有内部可以访问,外部不能访问
>>> 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方法
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方法
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修改方法为
bart.set_score(99)
原先直接通过bart.score=99也可以直接修改,为什么要定义一个方法大费周折?因为在方法中,可以对参数进行检查,避免传入无效的参数
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')
如果传递了无效的成绩会报错
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
变量:
>>> bart._Student__name
'Zhangsan'
但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name
改成不同的变量名。
注意下面这种错误写法
>>> 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
>>> bart.get_name()
'Zhangsan'
练习:
class Student(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
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则报错
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
Python3之类和实例访问限制的更多相关文章
- SQL ser 跨实例访问数据库
SqlServer如何跨实例访问数据库 Exec sp_droplinkedsrvlogin LinkName,NullExec sp_dropserver LinkName go EXEC sp_a ...
- static成员是可以被其所在class创建的实例访问!!!
<span style="font-family: Arial, Helvetica, sans-serif; ">关于静态方法以及静态变量的使用就不详细的说了,我就这 ...
- Python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的
转:http://www.cnblogs.com/2gua/ Python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的: 1)静态方法无需传入self参数,类成员方法 ...
- 通过FEDERATED存储引擎跨实例访问数据
通过FEDERATED存储引擎同步两实例间的表数据需求情景:实例1中A库中的三个视图是实例2中的B库所依赖的,B需要A库中三个视图的实时数据.方案:通过FEDERATED来完成跨势力的查询FEDERA ...
- Python3 的urllib实例
在Python3中合并了 urllib 和 urllib2, 统一命名为 urllib 了,我觉得这样更加合理了.让我们可以像读取本地文件一样读取WEB上的数据.封装了一个类,供以后方便使用吧!并附带 ...
- Python学习 Day 7 面向对象 类和实例 访问限制
面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程 ...
- Python3面向对象编程实例
/*认真研究完这个实例,理解python面向对象编程的方法*/class Person: """人员信息""" # 姓名(共有属性) nam ...
- python3类和实例
面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可 ...
- Python3之类和实例
面向对象的重要概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如学生类Student,而实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法,单各自的数据可能 ...
随机推荐
- jQuery相关方法9----事件相关
一.事件冒泡和阻止事件冒泡 <script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js"></s ...
- exam8.3
rank25凉凉好吧......T1:... 一开始完全** 手玩给的那张图(不放图,我太饿把图吃了) 发现对于任一个节点,减去上一个比他小的斐波那契数就是父 ...
- luogu 1369
给出平面上的n个点,请找出一个边与坐标轴平行的矩形,使得它的边界上有尽量多的点 模拟退火题解$n^2$ 处理每行的前缀和与每列的前缀和退火50次即可 #include <bits/stdc++. ...
- Bzoj 1566: [NOI2009]管道取珠(DP)
1566: [NOI2009]管道取珠 Time Limit: 20 Sec Memory Limit: 650 MB Submit: 1558 Solved: 890 [Submit][Status ...
- [转]C++重载()(强制类型转换运算符)
在 C++ 中,类型的名字(包括类的名字)本身也是一种运算符,即类型强制转换运算符. 类型强制转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数.经过适当重载后,(类型名) ...
- linux系列(十二):more命令
1.命令格式: more [-dlfpcsu ] [-num ] [+/ pattern] [+ linenum] [file] 2.命令功能: more命令和cat的功能一样都是查看文件里的内容,但 ...
- 使用开源软件 jumpserver 搭造自己的堡垒机
使用开源软件 jumpserver 搭造自己的堡垒机 开软地址:https://github.com/jumpserver/jumpserver 目前版本:1.5.2 测试的时候有少许BUG,但功能却 ...
- 遇到bug如何处理
issue中查询是否有相似bug assert / try-except / IDE单步调式 框架可以查询源码或者查询官方文档
- 快速打造自己的PHPStorm主题
---恢复内容开始--- 一个优雅和舒适的界面,可以增加过多写入代码的动力. Phpstorm小型的白色主题比较简陋.为了打造一个优雅和舒适的界面,我们安装一件叫Material Theme UI的插 ...
- elasticsearch alias
索引别名API允许使用一个名字来作为一个索引的别名,所有API会自动将别名转换为实际的索引名称. 别名也可以映射到多个索引,别名不能与索引具有相同的名称.别名可以用来做索引迁移和多个索引的查询统一,还 ...