python对象数据的读写权限
面向对象的编程语言在写大型程序的的时候,往往比面向过程的语言用起来更方便,安全。其中原因之一在于:类机制。
类,对众多的数据进行分类,封装,让一个数据对象成为一个完整的个体,贴近现实生活,高度抽象化。但是,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 file对象测试数据的读写操作及OS模块介绍(四)
import from....import 引入模块 引入类 ①import 如果文件在lib下而且是python模块 :import 模块名. ②from....import from 包名.包 ...
- python文件的读写权限以及相关应用read、write和文件指针
f=open('ceshi.txt','a',encoding='utf-8')r=open('ceshi.txt','r',encoding='utf-8')上面的2种写法可以用with来写:wit ...
- ubuntu 中 mongodb 数据读写权限配置
首先,我们先对mongodb 数据库的权限做一点说明: 1 默认情况下,mongodb 没有管理员账号 2 只有在 admin 数据库中才能添加管理员账号并开启权限 3 用户只能在所在的数据库中登录, ...
- 十:python 对象类型详解六:文件
一:文件 1.简介:内置open 函数会创建一个python 文件对象,可以作为计算机上的一个文件链接.在调用open 之后,可以通过调用返回文件对象的方法来读写相关外部文件.文件对象只是常见文件处理 ...
- cPickle对python对象进行序列化,序列化到文件或内存
pickle模块使用的数据格式是python专用的,并且不同版本不向后兼容,同时也不能被其他语言说识别.要和其他语言交互,可以使用内置的json包 cPickle可以对任意一种类型的python对象进 ...
- python基础之文件读写
python基础之文件读写 本节内容 os模块中文件以及目录的一些方法 文件的操作 目录的操作 1.os模块中文件以及目录的一些方法 python操作文件以及目录可以使用os模块的一些方法如下: 得到 ...
- 第二篇:python基础之文件读写
python基础之文件读写 python基础之文件读写 本节内容 os模块中文件以及目录的一些方法 文件的操作 目录的操作 1.os模块中文件以及目录的一些方法 python操作文件以及目录可以使 ...
- Python之数据序列化(json、pickle、shelve)
本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Py ...
- 使用Python对Excel进行读写操作
学习Python的过程中,我们会遇到Excel的读写问题.这时,我们可以使用xlwt模块将数据写入Excel表格中,使用xlrd模块从Excel中读取数据.下面我们介绍如何实现使用Python对Exc ...
随机推荐
- filter()函数 条件筛选
filter()函数 filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 ...
- Apple Watch开发快速入门教程
Apple Watch开发快速入门教程 试读下载地址:http://pan.baidu.com/s/1eQ8JdR0 介绍:苹果为Watch提供全新的开发框架WatchKit.本教程是国内第一本A ...
- oracle处理考勤时间,拆分考勤时间段的sql语句
最近一直在用mysql数据库做云项目,有段时间没有接触oracle了,昨天有朋友叫我帮忙用oracle处理一个考勤记录的需求,我在考虑如何尽量精简实现上面花了一些时间.于是把这个实现做个总结. 需求如 ...
- C# params参数的应用
为了将方法声明为可以接受可变数量参数的方法,我们可以使用params关键字来声明数组,如下所示: public static Int32Add(params Int32[] values) { Int ...
- BZOJ 2282 & 树的直径
SDOI2011的Dayx第2题 题意: 在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在 ...
- HTMl5/CSS3/Javascript 学习推荐资源
HTMl5/CSS3/Javascript 学习推荐资源 前端的定义应该是数据内容的展示,在国内大家都觉得前端只是HTML+CSS+Javascript,但是实际上与展示有关的都是前端,所以Ruby/ ...
- meta标签的用法
meta是用来在HTML文档中模拟HTTP协议的响应头报文.meta 标签用于网页的<head>与</head>中,meta 标签的用处很多.meta 的属性有两种:name和 ...
- FileStorage Read String Start With Number Need Quotation Mark 读取数字开头的字符串需要加引号
// Write data FileStorage fs("test.yml", FileStorage::WRITE); fs << "MyString&q ...
- git客户端初始化
安装git客户端:[root@super67 ~]# yum install -y git 配置git信息:[root@super67 ~]# git config --global user.nam ...
- Delphi 复习代码
1.取得可文件路径 Path := ExtractFilePath(Application.ExeName); //取得可执行文件路径 TXMLDocument.Create(ExtractFileP ...