浅谈python对象数据的读写权限


Posted in Python onSeptember 12, 2016

面向对象的编程语言在写大型程序的的时候,往往比面向过程的语言用起来更方便,安全。其中原因之一在于:类机制。

类,对众多的数据进行分类,封装,让一个数据对象成为一个完整的个体,贴近现实生活,高度抽象化。但是,python对类的封装并不好,因为所有的属性和方法都是公开的,你可以随意访问或者写入,你可以在类的外部对类的属性进行修改,甚至添加属性。这的确让人感到不安。

下面就来总结一下学习后的解决方案。

1,使用2个下划线前缀隐藏属性或者方法。

__xxx

#!/usr/bin/python3
#-*- coding:utf-8 -*-


class Student:
  def __init__(self,name,score):
    self.name = name
    self.__score = score #将score隐藏起来,使之仅在类内部可用。

  def __show(self):    #一个隐藏的方法,同样只在内部可用
    print(self.name,self.__score)#使用被隐藏的属性__score
    
  def Show(self):
    self.__show()    #注意被隐藏方法的调用方式。


  
def main():
  he = Student('Bob',95)
  he.Show()       #显示:Bob 95
  #print(he.__score)   #AttributeError: 'Student' object has no attribute '__score'
  #he.__show()      #AttributeError: 'Student' object has no attribute '__show'

  #隐藏属性真的被隐藏了吗?其实仍然可使用,使用格式 obj._className__attributeName
  #但是仅仅作为了解,不建议使用隐藏属性。
  print(he._Student__show())  #显示:Bob 95
  print(he._Student__score)   # 显示: 95
  
  
  

if __name__=="__main__":
  main()

双下划线对类属性的影响:

1. 使属性只用于本类的内部,外部以及子类都不可直接读取修改。

2. 使用 _ _ 的类的属性,在实现时会被更改名称,如类中的__age   最后会变为_A__age (名称重整),这个好处是:通常用于涉及到继承的父类中使用。这样避免被子类属性覆盖。

2.创建可管理的属性。

有时候我们需要对属性的写入做额外的检查,对不合法的值拒绝写入,引发异常。

#!/usr/bin/python3
#-*- coding:utf-8 -*-


class Student:
  def __init__(self,name,score):
    self.name = name
    self.score = score 

  @property        #实现属性的读取方法,读取实例的score值时,就会调用这个函数
  def score(self):
    return self.__score

  
  @score.setter     #实现属性写入方法,写入实例的score属性时,调用这个函数
  def score(self,newVal):
    if not isinstance(newVal,(int,float)):
      raise TypeError('score value must be a number')
    if newVal>100 or newVal<0:
      raise ValueError('score value must between 0 and 100')

    self.__score = newVal

  

  
def main():
  he = Student('Bob',95)
  he.score = 100   #重新写入 

  
  print(he.score)  #读取   
    
  

if __name__=="__main__":
  main()

我们可以发现:  self.__score是 属性值 的真正存储的地方,而self.score是函数(只不过它用起来像一个属性),它是获取和写入属性值的方法。

初始化的时候也会调用socre.setter 装饰的函数,因为__init__()函数下出现了self.score的调用

既然self.__score仅仅用来引用属性的值,可不可以用别的命名呢?如saveScore....当然是可以的,但是,它“暴露”了,我们不想让它在外部可用,还是应该

加 __ 将它隐藏,防止意外修改。

有时候,你确定某个类不会涉及到继承,那么,就可以将上述的双下划线改写为单下滑线,虽然不会达到隐藏的作用,但是:一方面,这样不会引发名称重整机制,

避免小题大做,另一面,用一个下划线开头,可以提醒使用者,这个属性不应该直接使用。那么,这就靠自觉了。

一个实例对象可以在外部随意添加属性。

#!/usr/bin/python3
#-*- coding:utf-8 -*-


class Student:
  def __init__(self,name,score):
    self.name = name
    self.score = score 

 

  
def main():
  he = Student('Bob',95)
  he.age = 19
  print(he.age)
  

if __name__=="__main__":
  main()

使用__slots__



#!/usr/bin/python3
#-*- coding:utf-8 -*-


class Student:
  __slots__ = ('name','score') #将属性名以字符串形式加入元组
  def __init__(self,name,score):
    self.name = name
    self.score = score 

 

  
def main():
  he = Student('Bob',95)
  he.age = 19  #AttributeError: 'Student' object has no attribute 'age'
  print(he.age)
  

if __name__=="__main__":
  main()

这样,对象的属性就限定在类的内部了。

但是__slots__不能被继承。而且,__slots__的设计本意并不是上面的用法,而是创建大量(万计)对象时对内存占用进行优化。

总结:

写着写着,我发觉上面的技巧意义不大。类的设计是程序员本人,使用者也是本人,那么,对象属性的

读和写就应该自己把握,类设计时本身不需要太多的保护代码,否则会很臃肿,而且效率降低。保护措施应该发生在类的外部,让类对象接受到的数据永远是合法的,这样会更加轻巧灵活。这是我的感受。

以上这篇浅谈python对象数据的读写权限就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python的PEAK来适配协议的教程
Apr 14 Python
Python变量和数据类型详解
Feb 15 Python
Numpy数据类型转换astype,dtype的方法
Jun 09 Python
解决sublime+python3无法输出中文的问题
Dec 12 Python
python实现网站用户名密码自动登录功能
Aug 09 Python
Python简易计算器制作方法代码详解
Oct 31 Python
python实现输出一个序列的所有子序列示例
Nov 18 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
Apr 24 Python
python函数调用,循环,列表复制实例
May 03 Python
python 解决Fatal error in launcher:错误问题
May 21 Python
升级keras解决load_weights()中的未定义skip_mismatch关键字问题
Jun 12 Python
详解使用python爬取抖音app视频(appium可以操控手机)
Jan 26 Python
python获取list下标及其值的简单方法
Sep 12 #Python
Python循环语句中else的用法总结
Sep 11 #Python
python字典键值对的添加和遍历方法
Sep 11 #Python
解决Python 遍历字典时删除元素报异常的问题
Sep 11 #Python
完美解决python遍历删除字典里值为空的元素报错问题
Sep 11 #Python
python 循环遍历字典元素的简单方法
Sep 11 #Python
遍历python字典几种方法总结(推荐)
Sep 11 #Python
You might like
如何做到多笔资料的同步
2006/10/09 PHP
Fine Uploader文件上传组件应用介绍
2013/01/06 PHP
PHP中使用数组指针函数操作数组示例
2014/11/19 PHP
php使用CutyCapt实现网页截图保存的方法
2016/10/03 PHP
PHP获取指定日期是星期几的实现方法
2016/11/30 PHP
PHP编程实现微信企业向用户付款的方法示例
2017/07/26 PHP
php提供实现反射的方法和实例代码
2019/09/17 PHP
关于onScroll事件在IE6下每次滚动触发三次bug说明
2011/09/21 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(二)人物行走的实现
2013/01/23 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
2016/03/22 Javascript
使用openSpeDiv方法实现Ecshop登录弹窗框效果
2017/03/13 Javascript
JS常见创建类的方法小结【工厂方式,构造器方式,原型方式,联合方式等】
2017/04/01 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
详解angularJS动态生成的页面中ng-click无效解决办法
2017/06/19 Javascript
JavaScript基于activexobject连接远程数据库SQL Server 2014的方法
2017/07/12 Javascript
Vue.js实现实例搜索应用功能详细代码
2017/08/24 Javascript
小程序开发中如何使用async-await并封装公共异步请求的方法
2019/01/20 Javascript
微信小程序扫描二维码获取信息实例详解
2019/05/07 Javascript
vue实现公告栏文字上下滚动效果的示例代码
2020/06/16 Javascript
Antd的table组件表格的序号自增操作
2020/10/27 Javascript
python定向爬虫校园论坛帖子信息
2018/07/23 Python
influx+grafana自定义python采集数据和一些坑的总结
2018/09/17 Python
python pandas读取csv后,获取列标签的方法
2018/11/12 Python
python:接口间数据传递与调用方法
2018/12/17 Python
pandas删除指定行详解
2019/04/04 Python
浅谈spring boot 集成 log4j 解决与logback冲突的问题
2020/02/20 Python
浅谈keras中的batch_dot,dot方法和TensorFlow的matmul
2020/06/18 Python
css3 pointer-events 介绍详解
2017/09/18 HTML / CSS
Vilebrequin美国官方网上商店:法国豪华泳装品牌
2020/02/22 全球购物
仓库管理专业个人自我评价范文
2013/11/11 职场文书
校园创业策划书
2014/01/14 职场文书
领导班子自我剖析材料
2014/08/16 职场文书
保密工作整改报告
2014/11/06 职场文书
比较node.js和Deno
2021/04/27 Javascript
SpringBoot+Redis实现布隆过滤器的示例代码
2022/03/17 Java/Android
PyCharm 配置SSH和SFTP连接远程服务器
2022/05/11 Python