“包装”在Python 编程中经常会被提到的一个术语。意思是对一个已存在的对象进行包装,可以是对一个已存在的对象,增加,删除,或者修改功能。

可以包装任何类型(type)作为一个类(class)的核心成员,以使新对象的行为模仿你想要的数据类型中已存在的行为,并且去掉你不希望存在的行为。

授权是包装的一个特性,实现授权的关键点就是覆盖__getattr__()方法,在其中包含一个对getattr()内建函数的调用。

特殊方法__getattr__()的工作方式是,当搜索一个属性时,任何局部对象首先被找到(定制的对象)。如果搜索失败了,则__getattr__()会被调用。

换言之,当引用一个属性时,Python 解释器将试着在局部名称空间中查找那个名字,如果没有在局部字典中找到,则搜索类名称空间,最后,如果两类搜索都失败了,搜索则对原对象开始授权请求,此时,__getattr__()会被调用。

包装的一个简单例子:

class  WrapMe(object):
def __init__(self, obj):
self.__data = obj
def get(self):
return self.__data
def __repr__(self):
return ‘self.__data‘
def __str__(self):
return str(self.__data)
def __getattr__(self, attr):
return getattr(self.__data, attr)

这里将用到复数,因为所有Python数值类型,只有复数拥有属性:

>>> wrapcomplex =WrapMe(3.5+4.2j)
>>> wrapcomplex
(3.5+4.2j) >>> wrapcomplex.real
3.5 >>> wrapcomplex.imag
4.2 >>>wrapcomplex.conjugate()
(3.5-4.2j) >>> wrapcomplex.get()
(3.5+4.2j)

访问复数的三种属性,我们的自定义类中一种都没有定义,对这些属性的访问,是通过getattr()方法,授权给对象。调用get()方法没有授权,因为它是为我们的对象定义的。

下一个使用包装类的例子用到一个列表。我们将会创建对象,然后执行多种操作,每次授权给列表方法。

>>> wraplist =WrapMe([123, 'foo', 45.67])
>>>wraplist.append('bar')
>>>wraplist.append(123) >>> wraplist
[123, 'foo', 45.67, 'bar',123] >>>wraplist.index(45.67)
2 >>>wraplist.count(123)
2 >>> wraplist.pop()
123 >>> wraplist
[123, 'foo', 45.67, 'bar']

注意,只有已存在的属性是在此代码中授权的。特殊行为没有在类型的方法列表中,不能被访问,因为它们不是属性。一个例子是,对列表的切片操作,它是内建于类型中的,而不是像append()方法那样作为属性存在的。也就是说,切片操作符是序列类型的一部分,并不是通过__getitem__()特殊方法来实现的。

>>> wraplist[2]
Traceback (most recent calllast):
File "<stdin>", line 1, in<module>
TypeError: 'WrapMe' objectdoes not support indexing

然而,还有一种"作弊"的方法,访问实际对象[通过get()方法]和它的切片能力.

>>> reallist =wraplist.get()
>>> reallist[3]
'bar'

这就是为什么需要实现get()方法了----仅仅是为了我们需要取得对原对象进行访问这种情况。

另外一个例子,描述了一个包装文件对象的类。我们的类与一般的文件对象行为完全一样, 除了在写模式中,字符串只有全部为大写时,才写入文件。下面提供一个文件类对象,定制write()方法,同时,给文件对象授权其它的功能:

class  CapOpen(object):
def __init__(self, fn,mode='r', buf=-1):
self.file = open(fn, mode, buf) def __str__(self):
return str(self.file) def __repr__(self):
return `self.file` def write(self, line):
self.file.write(line.upper()) def __getattr__(self, attr):
return getattr(self.file, attr) >>> f = CapOpen('/tmp/xxx','w')
>>>f.write('delegation example\n')
>>>f.write('faye is good\n')
>>>f.write('at delegating\n')
>>> f.close()
>>> f
<closed file '/tmp/xxx',mode 'w' at 12c230>

可以看到,唯一不同的是第一次对CapOpen()的调用,而不是open()。除了write(),所有属性都已授权给文件对象:

>>> f =CapOpen('/tmp/xxx', 'r')
>>> for eachLine in f:
... print eachLine,
... DELEGATION EXAMPLE
FAYE IS GOOD
AT DELEGATING

Python基础:21包装的更多相关文章

  1. 二十一. Python基础(21)--Python基础(21)

    二十一. Python基础(21)--Python基础(21) 1 ● 类的命名空间 #对于类的静态属性:     #类.属性: 调用的就是类中的属性     #对象.属性: 先从自己的内存空间里找名 ...

  2. 2015/10/9 Python基础(21):可调用和可执行对象

    在Python中有多种运行外部程序的方法,比如,运行操作系统命令或另外的Python脚本,或执行一个磁盘上的文件,或通过网络来运行文件.这完全取决于想要干什么.特定的环境包括: 在当前脚本继续运行 创 ...

  3. python基础(21):异常处理

    1. 异常和错误 1.1 错误 程序中难免出现错误,而错误分成两种 1.1.1 语法错误 语法错误:这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正. #语法错误示范一 if ...

  4. Python 基础 2-1 列表入门

    引言 列表 list 是由一系列按照特定顺序排列的元素组成的,它是一种有序的数据集合. 你可以添加任何类型的元素到列表中,其中的元素之间可以没有任何关系. 列表简介 Python 使用方括号 [] 来 ...

  5. python基础21 ------python基础之socket编程

    一.C/S架构和B/S架构的简介 略 二.osi七层模型 略 三.socket层 1.如图所示: socket层是存在于应用层和传输层直接抽象出来的一层. 2.socket层是什么? Socket是应 ...

  6. Python基础21

    对轴0,轴1,“axis”轴的理解很关键

  7. python网络爬虫实战PDF高清完整版免费下载|百度云盘|Python基础教程免费电子书

    点击获取提取码:vg1y python网络爬虫实战帮助读者学习Python并开发出符合自己要求的网络爬虫.网络爬虫,又被称为网页蜘蛛,网络机器人,是一种按照一定的规则,自动地抓取互联网信息的程序或者脚 ...

  8. Python学习--21天Python基础学习之旅(Day01、Day02)

    21天的python基础学习,使用<Python从入门到实践>,并且需要手敲书中的code,以下为整个学习过程的记录. Day01: 安装python时要选择复选框 Add Python ...

  9. Python基础教程 - Tdcqma

      1.1 普通字符串 1.21 错误与异常 1.41 XXXXXX 1.61 XXXXXX 1.81 XXXXXX 1.101 XXXXXX 1.2 转义字符串 1.22 装饰器         1 ...

  10. 进击的Python【第二章】:Python基础(二)

    Python基础(二) 本章内容 数据类型 数据运算 列表与元组的基本操作 字典的基本操作 字符编码与转码 模块初探 练习:购物车程序 一.数据类型 Python有五个标准的数据类型: Numbers ...

随机推荐

  1. LintCode_453 将二叉树拆成链表

    题目 将一棵二叉树按照前序遍历拆解成为一个假链表.所谓的假链表是说,用二叉树的 right 指针,来表示链表中的 next 指针. 样例 1 \ 1 2 / \ \ 2 5 => 3 / \ \ ...

  2. 【arc072e】AtCoder Regular Contest 072 E - Alice in linear land

    题意 给定一个D,以及一个长度为N的序列a,顺序执行这些数字: 对于一个数字x,会使得D=min(D,abs(D-x)) 有Q次询问,每次询问独立,给出i,能否修改a[i],使得D最后不为0. n,q ...

  3. poi操作word,简单写docx

    参考博客: https://www.cnblogs.com/guilty/p/3977016.html 在HWPF中换行符是"\013",在XWPF中是run.addBreak() ...

  4. IO流2 --- File类的常用方法1 --- 技术搬运工(尚硅谷)

    File类的获取功能 @Test public void test2(){ File file1 = new File("hello.txt"); File file2 = new ...

  5. JAVA短信验证码 工具类

    MsgCodeUtil.java package com.hg.util; import com.soyea.enums.ResultEnum; import com.soyea.exception. ...

  6. golang学习资料必备

    核心资料库 https://github.com/yangwenmai/learning-golang

  7. 各大ACM OJ网址

    做快乐的程序员 以你的条件,你不必追求优秀,但你可以做到良好. 各大OJ网址 ACM OJ Collection(排名不分先后): 中国:(China) 华东地区: 浙江: 杭州电子科技大学(HDU) ...

  8. pyenv虚拟环境管理python多版本和软件库

    可能大家在日常工作中会遇到这么个问题,现在基本的linux系统都是自带老版本的python2.7.x版本,我又不想用老版本,但直接升级可能会出问题,或是依赖老版本的程序就运行不了,有没办法能安装3.x ...

  9. Effective Modern C++:07并发API

    C++11的志伟功勋之一,就是将并发融入了语言和库中,因此在C++的历史上,程序员可以首次跨越所有平台撰写具有标准行为的多线程程序. 35:优先选用基于任务而非基于线程的程序设计 如果需要以异步的方式 ...

  10. 深入理解 Node.js 进程与线程

    原文链接: https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651557398&idx=1&sn=1fb991da ...