Python 访问限制 private public的详细介绍


Posted in Python onOctober 16, 2018

 一、知识点

在一个模块中,我们可能会定义很多函数和变量。但有的函数和变量我们希望能给别人使用,有的函数和变量我们希望仅仅在模块内部使用,so?
我们可以通过定义该函数、变量是公开的还是私有的来达到该目的。
在Python中,是通过下划线“_”前缀来实现的。

  • public:公开的。正常的函数和变量名为此类型,可以被直接引用。比如变量abc、PI等;
  • 特殊变量:格式为__xxx__ ,以__开头、以__结尾。可以直接被引用,但是有特殊用途。比如 __author__ 、__name__就是特殊变量。一般自己定义的变量不要用这种变量名。
  • private:私有的、非公开的,格式类似于_xxx_ 和__xxx,例如__num。

不应该被直接引用,只有内部可以访问,外部不能访问。

不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

二、举例说明

在Class类内部,可以有属性和方法。而外部代码可以通过直接调用实例变量的方法来操作数据,隐藏了内部复杂逻辑。但是,外部代码还是可以自由地修改一个实例的属性。例如:

>>>b.score
99
>>>b.score = 59
>>>b.score
59

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线“__”,变成私有变量,如下:

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('Bart Simpson', 98) 
>>> 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 get_name(self):     
    return self.__name   
  def get_score(self):     
    return self.__score

如果外部代码修改score怎么办?可以再给Student类增加设置方法:set_score():

...
def set_score(self, score): 
  # 避免传入无效参数 
  if 0 <= score <= 100: 
    self.__score = score 
  else:       
    raise ValueError('bad score')

那作为双下划线开头的私有实例变量是不是一定不能从外部访问呢?其实也不是。

不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以仍然可以通过_Student__name来访问__name变量。

>>> bart = Student('Bart Simpson', 98)
>>> bart.get_name() 
'Bart Simpson' 
>>> bart.__name = 'New Name' # 给bart新增的__name变量 
>>> bart.__name        # !与class内部的__name变量不是一个变量!
'New Name' 
>>> bart.get_name()      # get_name()内部返回self.__name (_Student__name)
'Bart Simpson'

表面上看,外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量。

所以python并没有一种方法可以完全限制访问private的函数或变量,所以不是“不能被直接引用”,从编程的习惯上不应该引用private函数或变量。那他们的用处呢?

例如:

def _private_1 (name):
  return 'hello,%s ' % name
def _private_2 (name):
  return 'hi , %s ' % name
def greeting(name):
  if len(name) > 3:
    return _private_1 (name)
  else:
    return _private_2 (name)

在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了。这样,调用greeting()函数不用关心内部的私有函数的细节。

这是一种非常有用的代码封装和抽象的方法,即:外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public。

三、完整代码

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')  
      
  def _private_1 (name):
    return 'hello,%s ' % name
  def _private_2 (name):
    return 'hi , %s ' % name
  def greeting(name):
    if len(name) > 3:
      return _private_1 (name)
    else:
      return _private_2 (name)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
解决Scrapy安装错误:Microsoft Visual C++ 14.0 is required...
Oct 01 Python
Python字典操作详细介绍及字典内建方法分享
Jan 04 Python
Python中生成器和迭代器的区别详解
Feb 10 Python
python实现pdf转换成word/txt纯文本文件
Jun 07 Python
浅析Python 3 字符串中的 STR 和 Bytes 有什么区别
Oct 14 Python
Mac下Anaconda的安装和使用教程
Nov 29 Python
Python获取好友地区分布及好友性别分布情况代码详解
Jul 10 Python
Python实现语音识别和语音合成功能
Sep 20 Python
pytorch加载语音类自定义数据集的方法教程
Nov 10 Python
python 统计代码耗时的几种方法分享
Apr 02 Python
python中pandas对多列进行分组统计的实现
Jun 18 Python
Python max函数中key的用法及原理解析
Jun 26 Python
对django中render()与render_to_response()的区别详解
Oct 16 #Python
浅谈django的render函数的参数问题
Oct 16 #Python
django之跨表查询及添加记录的示例代码
Oct 16 #Python
python看某个模块的版本方法
Oct 16 #Python
对python中的 os.mkdir和os.mkdirs详解
Oct 16 #Python
详解Django的model查询操作与查询性能优化
Oct 16 #Python
python查看模块,对象的函数方法
Oct 16 #Python
You might like
PHP更新购物车数量(表单部分/PHP处理部分)
2013/05/03 PHP
探讨PHP中OO之静态关键字以及类常量的详解
2013/06/07 PHP
强悍无比的WEB开发好助手FireBug(Firefox Plugin)
2007/01/16 Javascript
jquery一般方法介绍 入门参考
2011/06/21 Javascript
JavaScript 模拟类机制及私有变量的方法及思路
2013/07/10 Javascript
js判断字符长度以及中英文数字等
2013/12/31 Javascript
jQuery插件开发详细教程
2014/06/06 Javascript
jQuery获取某天的农历日期并判断是否除夕或新年的方法
2016/03/01 Javascript
JS产生随机数的用法小结
2016/12/10 Javascript
基于Bootstrap漂亮简洁的CSS3价格表(附源码下载)
2017/02/28 Javascript
JavaScript判断浏览器和hack滚动条的写法
2017/07/23 Javascript
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
2017/08/18 Javascript
nodejs中安装ghost出错的原因及解决方法
2017/10/23 NodeJs
JavaScript中var、let、const区别浅析
2018/06/24 Javascript
vue2.0 element-ui中el-select选择器无法显示选中的内容(解决方法)
2018/08/24 Javascript
Vue 利用指令实现禁止反复发送请求的两种方法
2019/09/15 Javascript
JavaScript使用prototype属性实现继承操作示例
2020/05/22 Javascript
关于ES6尾调用优化的使用
2020/09/11 Javascript
[03:57]《不朽》——2015DOTA2国际邀请赛—中国军团出征主题曲MV
2015/07/15 DOTA
Python中使用第三方库xlutils来追加写入Excel文件示例
2015/04/05 Python
实例说明Python中比较运算符的使用
2015/05/13 Python
Python调用系统底层API播放wav文件的方法
2017/08/11 Python
python删除文本中行数标签的方法
2018/05/31 Python
TensorFlow的权值更新方法
2018/06/14 Python
详解Django+Uwsgi+Nginx的生产环境部署
2018/06/25 Python
python的sorted用法详解
2019/06/25 Python
PyCharm Community安装与配置的详细教程
2020/11/24 Python
如何用python批量调整视频声音
2020/12/22 Python
HTML5注册表单的自动聚焦与占位文本示例代码
2013/07/19 HTML / CSS
idealfit英国:世界领先的女性健身用品和运动衣物品牌
2017/11/25 全球购物
香港交友网站:be2香港
2018/07/22 全球购物
会计学应届毕业生推荐信
2013/11/04 职场文书
优秀干部获奖感言
2014/01/31 职场文书
2015小学五年级班主任工作总结
2015/05/21 职场文书
分家协议书范本
2016/03/22 职场文书
【HBU】数据库第四周 单表查询
2021/04/05 SQL Server