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

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

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

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

  1. #!/usr/bin/python3
  2. #-*- coding:utf-8 -*-
  3.  
  4. class Student:
  5. def __init__(self,name,score):
  6. self.name = name
  7. self.__score = score #将score隐藏起来,使之仅在类内部可用。
  8.  
  9. def __show(self): #一个隐藏的方法,同样只在内部可用
  10. print(self.name,self.__score)#使用被隐藏的属性__score
  11.  
  12. def Show(self):
  13. self.__show() #注意被隐藏方法的调用方式。
  14.  
  15. def main():
  16. he = Student('Bob',95)
  17. he.Show() #显示:Bob 95
  18. #print(he.__score) #AttributeError: 'Student' object has no attribute '__score'
  19. #he.__show() #AttributeError: 'Student' object has no attribute '__show'
  20.  
  21. #隐藏属性真的被隐藏了吗?其实仍然可使用,使用格式 obj._className__attributeName
  22. #但是仅仅作为了解,不建议使用隐藏属性。
  23. print(he._Student__show()) #显示:Bob 95
  24. print(he._Student__score) # 显示: 95
  25.  
  26. if __name__=="__main__":
  27. main()

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

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

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

2.创建可管理的属性。

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

  1. #!/usr/bin/python3
  2. #-*- coding:utf-8 -*-
  3.  
  4. class Student:
  5. def __init__(self,name,score):
  6. self.name = name
  7. self.score = score
  8.  
  9. @property #实现属性的读取方法,读取实例的score值时,就会调用这个函数
  10. def score(self):
  11. return self.__score
  12.  
  13. @score.setter #实现属性写入方法,写入实例的score属性时,调用这个函数
  14. def score(self,newVal):
  15. if not isinstance(newVal,(int,float)):
  16. raise TypeError('score value must be a number')
  17. if newVal>100 or newVal<0:
  18. raise ValueError('score value must between 0 and 100')
  19.  
  20. self.__score = newVal
  21.  
  22. def main():
  23. he = Student('Bob',95)
  24. he.score = 100 #重新写入
  25.  
  26. print(he.score) #读取
  27.  
  28. if __name__=="__main__":
  29. main()

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

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

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

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

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

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

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

  1. #!/usr/bin/python3
  2. #-*- coding:utf-8 -*-
  3.  
  4. class Student:
  5. def __init__(self,name,score):
  6. self.name = name
  7. self.score = score
  8.  
  9. def main():
  10. he = Student('Bob',95)
  11. he.age = 19
  12. print(he.age)
  13.  
  14. if __name__=="__main__":
  15. main()

使用__slots__

  1. #!/usr/bin/python3
  2. #-*- coding:utf-8 -*-
  3.  
  4. class Student:
  5. __slots__ = ('name','score') #将属性名以字符串形式加入元组
  6. def __init__(self,name,score):
  7. self.name = name
  8. self.score = score
  9.  
  10. def main():
  11. he = Student('Bob',95)
  12. he.age = 19 #AttributeError: 'Student' object has no attribute 'age'
  13. print(he.age)
  14.  
  15. if __name__=="__main__":
  16. main()

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

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

总结:

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

读和写就应该自己把握,类设计时本身不需要太多的保护代码,否则会很臃肿,而且效率降低。保护措施应该发生在类的外

部,让类对象接受到的数据永远是合法的,这样会更加轻巧灵活。这是我的感受。

python对象数据的读写权限的更多相关文章

  1. python file对象测试数据的读写操作及OS模块介绍(四)

    import   from....import 引入模块 引入类 ①import 如果文件在lib下而且是python模块 :import 模块名. ②from....import from 包名.包 ...

  2. python文件的读写权限以及相关应用read、write和文件指针

    f=open('ceshi.txt','a',encoding='utf-8')r=open('ceshi.txt','r',encoding='utf-8')上面的2种写法可以用with来写:wit ...

  3. ubuntu 中 mongodb 数据读写权限配置

    首先,我们先对mongodb 数据库的权限做一点说明: 1 默认情况下,mongodb 没有管理员账号 2 只有在 admin 数据库中才能添加管理员账号并开启权限 3 用户只能在所在的数据库中登录, ...

  4. 十:python 对象类型详解六:文件

    一:文件 1.简介:内置open 函数会创建一个python 文件对象,可以作为计算机上的一个文件链接.在调用open 之后,可以通过调用返回文件对象的方法来读写相关外部文件.文件对象只是常见文件处理 ...

  5. cPickle对python对象进行序列化,序列化到文件或内存

    pickle模块使用的数据格式是python专用的,并且不同版本不向后兼容,同时也不能被其他语言说识别.要和其他语言交互,可以使用内置的json包 cPickle可以对任意一种类型的python对象进 ...

  6. python基础之文件读写

    python基础之文件读写 本节内容 os模块中文件以及目录的一些方法 文件的操作 目录的操作 1.os模块中文件以及目录的一些方法 python操作文件以及目录可以使用os模块的一些方法如下: 得到 ...

  7. 第二篇:python基础之文件读写

    python基础之文件读写   python基础之文件读写 本节内容 os模块中文件以及目录的一些方法 文件的操作 目录的操作 1.os模块中文件以及目录的一些方法 python操作文件以及目录可以使 ...

  8. Python之数据序列化(json、pickle、shelve)

    本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Py ...

  9. 使用Python对Excel进行读写操作

    学习Python的过程中,我们会遇到Excel的读写问题.这时,我们可以使用xlwt模块将数据写入Excel表格中,使用xlrd模块从Excel中读取数据.下面我们介绍如何实现使用Python对Exc ...

随机推荐

  1. Knowledgeroot安装与使用入门

    采用 PHP 开发的知识库系统,基于树状结构对内容进行组织.使用 FCKEditor 进行内容编辑. 效果http://demo.knowledgeroot.org/index.php?id=2230 ...

  2. RabbitMQ原理

    vhosts(broker) connection 与 channel(连接与信道) exchange 与  routingkey(交换机与路由键) queue(队列) Binding(绑定) cli ...

  3. SU Demos-02Filtering-07Sumedian

    不足之处,欢迎批评指正. 先看脚本内容: 脚本中用到的4个参数文件,是一系列x,t数据对,数组(x,t) 运行结果,

  4. 状压DP SGU 223 Little Kings

    题目传送门 /* 题意:n*n的矩阵,放置k个king,要求king互相不能攻击,即一个king的8个方向都没有另外的king,求方案个数 状态压缩DP:dp[i][num[j]][s] 代表在第i行 ...

  5. 使用INFORMATION_SCHEMA.Columns查询数据表结构

    使用情形1:写数据字典(Word文档)时, 需要获取表结构,以加快书写速度,当然,前提是没有文档导出工具. 使用情形2:生成实体时, 前提也是没有代码生成工具. 脚本 SELECT A.COLUMN_ ...

  6. BZOJ3356 : [Usaco2004 Jan]禁闭围栏

    首先将坐标离散化,考虑从左往右扫描线 碰到插入操作则插入 碰到删除操作的: 当前包含i的矩形数=y1在[1,y2[i]]之间的矩形数-y2在[1,y1[i]-1]之间的矩形数 用两棵树状数组维护即可, ...

  7. BZOJ3251 : 树上三角形

    BZOJ AC1000题纪念~~~ 将x到y路径上的点权从小到大排序 如果不存在b[i]使得b[i]+b[i+1]>b[i+2]则无解 此时b数列增长速度快于斐波那契数列,当达到50项时就会超过 ...

  8. Update From 用法

    今天遇到用一个表的字段填充另一个表的问题,整理了一下   1.在mysql中,应该使用inner join,即: UPDATE   a INNER JOIN b ON a.userName = b.u ...

  9. FXK Javascript

    Javascript是一门神奇的语言,很不爽的一门语言,很纠结的一门语言. 以下内容,专业人士请不要看,只供像我一样的菜鸟参考. (1)Javascript找不到函数.明明已经引用了JS文件,却提示找 ...

  10. 关于isset使用产生Can't use function return value in write context错误

    在使用isset检测session的一个取值是否存在时,产生了这个问题 翻译一下:不能在填写的内容中使用函数的返回值.然后我查看了php手册看isset函数的使用:isset()只能用于变量,因为传递 ...