【Python046--魔法方法:描述符】
一、描述符的定义:
描述符就是将特殊类型的类的实例指派给另外一个类的属性
1、举例:
特殊类型的类要实现以下三个方法中的其中一个或者全部实现
* __get__(self,instance,owner)
--用于访问属性,它返回属性的值
* __set__(self,instance,value)
--用于设置属性,不返回任何内容
* __delete__(self,instance)
--控制删除操作,不返回任何内容
class MyDecriptor:
def __get__(self,instance,owner):
#打印查看描述符的get,set,delete方法中各个参数的含义
print("getting...",self,instance,owner) def __set__(self,instance,value):
print("setting...",self,instance,value) def __delete__(self,instance):
print("deleteing...",self,instance) class Test:
#把特殊类MyDecriptor的实例指派给Test类的x属性
x = MyDecriptor() 执行结果:
>>> test = Test()
>>> test.x
getting... <__main__.MyDecriptor object at 0x10a2186d8> <__main__.Test object at 0x10a208f60> <class '__main__.Test'>
>>> test
<__main__.Test object at 0x10a208f60>
>>> Test
<class '__main__.Test'> '''
|--由打印出来的getting...,可以看出来,参数self是MyDecriptor的对象(<__main__.MyDecriptor object at 0x10a2186d8>)
|--参数instance是Test的对象(<__main__.Test object at 0x10a208f60>)
|--参数owner是Test的本类自己(<class '__main__.Test'>)
|--具体可由对象test打印出来的内容,和Test类打印出来的内容得到验证
|--set和delete同理
'''
>>> test.x = "X-man"
setting... <__main__.MyDecriptor object at 0x10a2186d8> <__main__.Test object at 0x10a208f60> X-man
>>> del test.x
deleteing... <__main__.MyDecriptor object at 0x10a2186d8> <__main__.Test object at 0x10a208f60>
>>>
2、为了能让描述符正常使用,必须定义在类的层次上,如果不是在类的层次上,Python无法会为你自动调用__get__(),__set__()方法
>>> class MyDes:
def __init__(self, value = None):
self.val = value
def __get__(self, instance, owner):
return self.val ** 2 >>> class Test:
def __init__(self):
self.x = MyDes(3) #用在了使用类的方法上,则不会调用描述符的__get__()和__set__()方法 >>> test = Test()
>>> test.x
<__main__.MyDes object at 0x109715588>
二、动手题
1、按要求编写描述符MyDes:当类的属性被访问,修改或设置的时候,分别作出提示
#当类的属性被访问,修改或设置时,分别给出提示
class MyDes:
def __init__(self,initval=None,name=None):
self.val = initval
self.name = name def __get__(self,instance,owner):
print("正在获取变量:",self.name)
return self.val def __set__(self,instance,value):
print("正在设置变量:",self.name)
self.var = value def __delete__(self,instance):
print("正在删除变量:",self.name)
print("不能删除变量!") class Test:
x = MyDes(10,'x') 执行结果: >>> test = Test()
>>> test.x
正在获取变量: x
10
>>> test.x = 'X-man'
正在设置变量: x
>>> del test.x
正在删除变量: x
不能删除变量!
>>> test.x
正在获取变量: x
10
2、按要求编写描述符MyDes:记录指定变量的读取和写入操作,并将记录以及触发时间保存到文件:record.txt
考察的内容:字符串的读取,文件的操作,time模块的用法,描述符
import time as t class MyDes:
def __init__(self,initval=None,name=None):
self.var = initval
self.name = name
self.filename = "record.txt" def __get__(self,instance,owner):
with open(self.filename,'a',encoding='utf-8') as f:
f.write("%s变量于北京时间%s被读取,%s = %s\n" % (self.name,t.ctime(),self.name,str(self.var))) print("var==", self.var)
return self.var def __set__(self, instance, value):
filename = "%s_record.txt" % self.name
with open(self.filename,'a',encoding='utf-8') as f:
f.write("%s变量于北京时间%s被修改,%s = %s\n" %(self.name,t.ctime(),self.name,str(value))) print("value==",value)
return value class Test:
x=MyDes(10,'x')
y=MyDes(8.8,'y') if __name__ == '__main__':
for i in range(10):
test = Test()
print("get_testX++",test.x,"\nget_testY--",test.y)
test.x = 123
test.x = 1.23
test.y = "I LOVE AI"
print("\n==================") 执行结果:
var== 10
var== 8.8
get_testX++ 10
get_testY-- 8.8
value== 123
value== 1.23
value== I LOVE AI ==================
var== 10
var== 8.8
get_testX++ 10
get_testY-- 8.8
value== 123
value== 1.23
value== I LOVE AI x变量于北京时间Wed Nov 14 23:32:54 2018被读取,x = 10
y变量于北京时间Wed Nov 14 23:32:54 2018被读取,y = 8.8
x变量于北京时间Wed Nov 14 23:32:54 2018被修改,x = 123
x变量于北京时间Wed Nov 14 23:32:54 2018被修改,x = 1.23
y变量于北京时间Wed Nov 14 23:32:54 2018被修改,y = I LOVE AI
x变量于北京时间Wed Nov 14 23:32:54 2018被读取,x = 10
y变量于北京时间Wed Nov 14 23:32:54 2018被读取,y = 8.8
x变量于北京时间Wed Nov 14 23:32:54 2018被修改,x = 123
x变量于北京时间Wed Nov 14 23:32:54 2018被修改,x = 1.23
y变量于北京时间Wed Nov 14 23:32:54 2018被修改,y = I LOVE AI
3、编写描述符MyDes,使用文件来存储属性,属性的值会被存放到对应的pickle文件内(腌菜),如果属性被删除了,文件也会同时被删除,属性的名字也会被注销
# coding=utf-8
import os
import pickle class MyDes:
saved = [] def __init__(self,name= None):
self.name = name
self.filename = self.name + '.pkl' def __get__(self, instance, owner):
if self.name not in MyDes.saved:
raise AttributeError("%s 的属性没有被赋值!"%self.name) with open(self.filename,'rb') as f:
value = pickle.load(f)
print("value++ ",value) return value def __set__(self, instance, value):
with open(self.filename,'wb') as f:
pickle.dump(value,f)
MyDes.saved.append(self.name)
print("f_name ",MyDes.saved) with open(self.filename,'rb') as f:
f_value = pickle.load(f)
print("f_value-- ",f_value) def __delete__(self, instance):
os.remove(self.filename)
MyDes.saved.remove(self.name) class Test:
x = MyDes('x')
y = MyDes('y') if __name__ == '__main__':
test = Test()
test.x = ''
test.y = 'I LOVE AI'#del test.y 执行结果:
f_name ['x']
f_value-- 123
f_name ['x', 'y']
f_value-- I LOVE AI
value++ 123
value++ I LOVE AI 并且生成两个pkl文件:x.pkl y,pkl
扩展知识:
1、用于序列化的两个模块
json:用于字符串和Python数据类型间进行转换
pickle:用于Python特有的类型和Python的数据类型间进行转换
json提供四个功能:dumps,dump,loads,load
pickle提供四个功能:dumps,dump,loads,load
2、pickle可以存储什么类型的数据呢?
1)、所有python支持的原生类型:布尔型,整形,浮点型,复数,字符串,字节,None
2)、由任何原生类型组成的列表,数组,字典
3)、函数,类和类的实例
3、pickle中常用的方法有:
1)、pickle.dump(obj,file,protocol=none)
必填参数obj表示要封装的对象
必填参数file表示obj要写入的文件对象,file必须以二进制可写模式打开,即:wb
可选参数protocol表示告知pickler使用的协议,支持的协议有0,1,2,3 默认的协议是添加在Python3中的协议3
with open(self.filename,'wb') as f:
pickle.dump(value,f)
MyDes.saved.append(self.name)
print("f_name ",MyDes.saved) #pickle.dump(obj,file)的使用必须结合open(file,'wb')
2)、 pickle.load(file,*,fix_imports=True, encoding="ASCII", errors="strict")
必填参数file必须已二进制可读模式打开,即:wb,其他都为可选参数
with open(self.filename,'rb') as f:
f_value = pickle.load(f)
print("f_value-- ",f_value) #pickle.load(file)的使用必须结合open(file,'rb')
3)、pickle.dumps(obj):已字节对象形式返回封装的对象,不需要写入文件中
4)、pickle.loads(bytes_object):从字节对象中读取被封装的对象,并返回
4、pickle模块可能出现三种异常:
1). PickleError:封装和拆封时出现的异常类,继承自Exception
2). PicklingError: 遇到不可封装的对象时出现的异常,继承自PickleError
3). UnPicklingError: 拆封对象过程中出现的异常,继承自PickleError
【Python046--魔法方法:描述符】的更多相关文章
- NDK开发之获得域和方法描述符
在NDK开发之调用方法和NDK开发之访问域两篇博客中,我们在获得域ID和方法ID时都需要一个叫做描述符的参数,那么在实际开发中我们怎么知道我们要调用的域或者方法的描述符呢? 一个简单的方法就是使用Ja ...
- python - 数据描述符(class 内置 get/set/delete方法 )
数据描述符(class 内置 get/set/del方法 ): # 什么是描述符 # 官方的定义:描述符是一种具有“捆绑行为”的对象属性.访问(获取.设置和删除)它的属性时,实际是调用特殊的方法(_g ...
- python2.7高级编程 笔记二(Python中的描述符)
Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些" ...
- 【python】描述符descriptor
开始看官方文档,各种看不懂,只看到一句Properties, bound and unbound methods, static methods, and class methods are all ...
- Python描述符(descriptor)解密(转)
原文:http://www.geekfan.net/7862/ Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装 ...
- 11.python描述符---类的装饰器---@property
描述符1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()这三个内置方法中的一个,描述符也被称为描述符协议(1):__ ...
- Python——描述符(descriptor)解密
本文由 极客范 - 慕容老匹夫 翻译自 Chris Beaumont.欢迎加入极客翻译小组,同我们一道翻译与分享.转载请参见文章末尾处的要求. Python中包含了许多内建的语言特性,它们使得代码简洁 ...
- Python 描述符 (descriptor)
1.什么是描述符? 描述符是Python新式类的关键点之一,它为对象属性提供强大的API,你可以认为描述符是表示对象属性的一个代理.当需要属性时,可根据你遇到的情况,通过描述符进行访问他(摘自Pyth ...
- 杂项之python描述符协议
杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用 ...
- [转]jni数据类型映射、域描述符说明
在Java存在两种数据类型: 基本类型 和 引用类型 ,大家都懂的 . 在JNI的世界里也存在类似的数据类型,与Java比较起来,其范围更具严格性,如下: 1.primitive types ---- ...
随机推荐
- SQL Server数据库(时间戳timestamp)类型
1.公开数据库中自动生成的唯一二进制数字的数据类型. 2.timestamp 通常用作给表行加版本戳的机制. 3.存储大小为 8 个字节. 不可为空的 timestamp 列在语义上等价于 binar ...
- beego 初体验 - orm - 增删改查
本文记录一下 beego orm 简单的增删改查,大牛请绕道. 首先,注册4个增删改查的路由: 其次,在 views 文件夹下增加对应的模板(页面): controller 类里写上增删改查的方法: ...
- Android -- 使用WindowManager实现悬浮框效果
1,原文在这里http://blog.csdn.net/qq_17250009/article/details/52908791,我只是把里面的关键步骤给注释了一下,首先来看一下我们的效果,如图(电脑 ...
- linux常见运维题
linux运维题 一.填空题 1. 在Linux 系统 中,以文件方式访问设备 . (linux下一切都是文件) 2. Linux 内核引导时,从文件/etc/fstab中读取要加载的文件系统 . ( ...
- 如何让多个dz论坛共用一个用户数据库
用户数据库在论坛中是可以独立备份的,备份方法:论坛后台——站长——数据库,备份所有ucenter数据表,也就是用户数据.其他DZ论坛搭建完成以后,可以上传用户数据库,将备份文件使用上传至网站所使用的主 ...
- 5.JVM的内存区域划分
一.JVM介绍 1. 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟 ...
- Python2.6 升级2.7
一. Centos6 默认为python2.6且不可卸载(因为Centos6深度依赖Python),要想升级为2.7 只能通过全新升级 操作如下: 1.下载 Python2.7 网址 https:// ...
- jQuery选择器--selector1,selector2,selectorN和ancestor descendant
selector1,selector2,selectorN 概述 将每一个选择器匹配到的元素合并后一起返回.你可以指定任意多个选择器,并将匹配到的元素合并到一个结果内 参数 selector1 ...
- Spark学习之路 (五)Spark伪分布式安装
一.JDK的安装 JDK使用root用户安装 1.1 上传安装包并解压 [root@hadoop1 soft]# tar -zxvf jdk-8u73-linux-x64.tar.gz -C /usr ...
- Spring整合Shiro
apache shiro 是一个安全认证框架,和 spring security 相比,在于他使用了比较简洁易懂的 认证和授权方式.其提供的 native-session(即把用户认证后的授权信息保存 ...