在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之类和实例访问限制的更多相关文章

  1. SQL ser 跨实例访问数据库

    SqlServer如何跨实例访问数据库 Exec sp_droplinkedsrvlogin LinkName,NullExec sp_dropserver LinkName go EXEC sp_a ...

  2. static成员是可以被其所在class创建的实例访问!!!

    <span style="font-family: Arial, Helvetica, sans-serif; ">关于静态方法以及静态变量的使用就不详细的说了,我就这 ...

  3. Python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的

    转:http://www.cnblogs.com/2gua/ Python的静态方法和类成员方法都可以被类或实例访问,两者概念不容易理清,但还是有区别的: 1)静态方法无需传入self参数,类成员方法 ...

  4. 通过FEDERATED存储引擎跨实例访问数据

    通过FEDERATED存储引擎同步两实例间的表数据需求情景:实例1中A库中的三个视图是实例2中的B库所依赖的,B需要A库中三个视图的实时数据.方案:通过FEDERATED来完成跨势力的查询FEDERA ...

  5. Python3 的urllib实例

    在Python3中合并了 urllib 和 urllib2, 统一命名为 urllib 了,我觉得这样更加合理了.让我们可以像读取本地文件一样读取WEB上的数据.封装了一个类,供以后方便使用吧!并附带 ...

  6. Python学习 Day 7 面向对象 类和实例 访问限制

    面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程 ...

  7. Python3面向对象编程实例

    /*认真研究完这个实例,理解python面向对象编程的方法*/class Person: """人员信息""" # 姓名(共有属性) nam ...

  8. python3类和实例

    面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可 ...

  9. Python3之类和实例

    面向对象的重要概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如学生类Student,而实例是根据类创建出来的一个个具体的对象,每个对象都拥有相同的方法,单各自的数据可能 ...

随机推荐

  1. 【bzoj3238】差异 后缀树

    题目大意:给你一个字符串$S$,设$S_i$是串$S$第$i$长的后缀,求: $\sum\limits_{i=1}^{|S|} \sum\limits_{j=i+1}^{|S|} |S_i|+|S_j ...

  2. fsLayuiPlugin树+数据表格使用

    fsLayuiPlugin 是一个基于layui的快速开发插件,支持数据表格增删改查操作,提供通用的组件,通过配置html实现数据请求,减少前端js重复开发的工作. GitHub下载 码云下载 测试环 ...

  3. 系统空闲时间 解决 GetLastInputInfo 负数问题

    using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices ...

  4. dubbo-本地直连

    一.背景 目前项目是基于dubbo做为rpc,zk为注册中心实现多个微服务之间的远程服务调用.但需要本地联调dubbo接口时,需要绕过注册中心,达到不干扰线上服务,即只订阅不注册服务的目的. 二.实现 ...

  5. 005_硬件基础电路_PCB安规设计规范

    包含两个文件:讲解pcb绘制过程中的安规要求 002_2_PCB安规设计规范(原创-绝对经典全面-玩转高压PCB设计)总结 002_3_电气间隙和爬电距离规定 链接:https://pan.baidu ...

  6. 心跳(纯代码制作心形,animation动画)

    思路:利用两个长方形(比例是2:3 | 3:2)可以合成心形,然后利用动画,缩放大小实现心跳(纯代码),效果如下: <body> <div></div> </ ...

  7. P1213 时钟

    题目描述 考虑将如此安排在一个 3 x 3 行列中的九个时钟: 目标要找一个最小的移动顺序将所有的指针指向12点.下面原表格列出了9种不同的旋转指针的方法,每一种方法都叫一次移动.选择1到9号移动方法 ...

  8. base/7/x86_64/filelists_db FAILED

      解决办法: [root@localhost ~]# cd /var/lib/rpm [root@localhost rpm]# rm -rf __db.* # 清除原 rpmdb 文件 [root ...

  9. Yarn状态机

    1 概述 为了增大并发性,Yarn采用事件驱动的并发模型,将各种处理逻辑抽象成事件和调度器,将事件的处理过程用状态机表示.什么是状态机? 如果一个对象,其构成为若干个状态,以及触发这些状态发生相互转移 ...

  10. x2goserver 连接问题

    The remote proxy closed the connection while negotiating the session. This may be due to the wrong a ...