- 浏览: 564907 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (478)
- lucene (45)
- oracle (19)
- nutch (2)
- blog (2)
- 垂直搜索 (19)
- java综合 (89)
- spring (15)
- Hibernate (9)
- Struts (9)
- Hadoop (16)
- Mysql (12)
- nosql (10)
- Linux (3)
- MyEclipse (4)
- Ant (1)
- 设计模式 (19)
- JBPM (1)
- JSP (1)
- HtmlParser (5)
- SVN (2)
- 插件 (2)
- 收藏 (7)
- Others (1)
- Heritrix (18)
- Solr (4)
- 主题爬虫 (31)
- 内存数据库 (24)
- 分布式与海量数据 (32)
- httpclient (14)
- Tomcat (1)
- 面试宝典 (6)
- Python (14)
- 数据挖掘 (1)
- 算法 (6)
- 其他 (4)
- JVM (12)
- Redis (18)
最新评论
-
hanjiyun:
本人水平还有待提高,进步空间很大,看这些文章给我有很大的指导作 ...
JVM的内存管理 Ⅲ -
liuxinglanyue:
四年后的自己:这种方法 不靠谱。 使用javaagent的方式 ...
计算Java对象占用内存空间的大小(对于32位虚拟机而言) -
jaysoncn:
附件在哪里啊test.NoCertificationHttps ...
使用HttpClient过程中常见的一些问题 -
231fuchenxi:
你好,有redis,memlink,mysql的测试代码吗?可 ...
MemLink 性能测试 -
guyue1015:
[color=orange][/color][size=lar ...
JAVA同步机制
转自:Cesar Otero
简介: Python 3 是 Guido van Rossum 功能强大的通用编程语言的最新版本。它虽然打破了与 2.x 版本的向后兼容性,但却清理了某些语法方面的问题。本文是这个由两部分组成的系列文章中的第二篇,本文构建在此系列 前一期文章 的基础之上,内容涵盖了 Python 更多的新特性和更高深的一些主题,比如在抽象基类、元类和修饰符等方面的变化。
有关 Python 版本 3—,也即 Python 3000 或 Py3K— 的前一篇文章讨论了 Python 内打破向后兼容性的一些基本变化,比如新的print()
函数、 bytes
数据类型以及 string
类型的变化。本文是该系列文章的第 2 部分,探究了更为高深的一些主题,比如抽象基类(ABC)、元类、函数注释和修饰符(decorator)、整型数(integer literal)支持、数值类型层次结构以及抛出和捕获异常,其中的大多数特性仍然会打破与版本 2x 产品线的向后兼容性。
在 Python 之前的版本中,对方法的转换必须在方法定义之后进行。对于较长的方法,此要求将定义的重要组成部分与 Python Enhancement Proposal (PEP) 318(有关链接,请参见 参考资料)给出的外部接口定义分离。下面的代码片段演示了这一转换要求:
def myMethod(self): # do something myMethod = transformMethod(myMethod) |
为了让此类情景更易于读懂,也为了避免必须多次重用相同的方法名,在 Python 版本 2.4 中引入了方法修饰符。
修饰符 是一些方法,这些方法可以修改其他方法并返回一个方法或另外一个可调用对象。对它们的注释是在修饰符的名称前冠以 “at” 符号(@
)— 类似 Java™ 注释的语法。清单 2 显示了实际应用中的修饰符。
@transformMethod def myMethod(self): # do something |
修饰符是一些纯粹的语法糖(syntactic sugar)— 或者(如 Wikipedia 所言)“对计算机语言语法的补充,这些补充并不影响语言的功能,而是会让语言变得更易于被人使用。”修饰符的一种常见用法是注释静态方法。比如,清单 1 和清单 2 相当,但清单 2 更容易被人读懂。
定义修饰符与定义其他方法无异:
def mod(method): method.__name__ = "John" return method @mod def modMe(): pass print(modMe.__name__) |
更棒的是 Python 3 现在不仅支持针对方法的修饰符,并且支持针对类的修饰符,所以,取代如下的用法:
class myClass: pass myClass = doSomethingOrNotWithClass(myClass) |
我们可以这样使用:
@doSomethingOrNotWithClass class myClass: pass |
元类 是这样一些类,这些类的实例也是类。Python 3 保留了内置的、用来创建其他元类或在运行时动态创建类的 metaclass
类型。如下的语法仍旧有效:
>>>aClass = type('className', (object,), {'magicMethod': lambda cls : print("blah blah")}) |
上述语法接受的参数包括:作为类名的字符串、被继承对象的元组(可以是一个空的元组)和一个包含可以添加的方法的字典(也可以是空的)。当然,也可以从类型继承并创建您自己的元类:
class meta(type): def __new__(cls, className, baseClasses, dictOfMethods): return type.__new__(cls, className, baseClasses, dictOfMethods) |
只允许关键字的参数
Python 3 已经更改了函数参数分配给 “参数槽(parameter slot)” 的方式,可以在传递进的参数内使用星号(*
)以便不接受可变长度的参数。命名的参数必须在 *
之后 — 比如,def meth(*, arg1): pass
。更多信息,请参考 Python 文档或 PEP 3102(有关链接,请参见 参考资料)。
注意:如果上面两个例子起不到任何作用,我强烈建议您阅读 David Mertz 和 Michele Simionato 合写的有关元类的系列文章。相关链接,请参见 参考资料。
请注意,现在,在类定义中,关键字参数被允许出现在基类列表之后 — 通常来讲,即 class Foo(*bases, **kwds): pass
。使用关键字参数metaclass
将元类传递给类定义。比如:
>>>class aClass(baseClass1, baseClass2, metaclass = aMetaClass): pass |
旧的元类语法是将此元类分配给内置属性 __metaclass__
:
class Test(object): __metaclass__ = type |
而且,既然有了新的属性 — __prepare__
— 我们就可以使用此属性为新的类名称空间创建字典。在类主体被处理之前,先会调用它,如清单 3 所示。
清单 3. 使用 the __prepare__ attribute 的一个简单元类
def meth(): print("Calling method") class MyMeta(type): @classmethod def __prepare__(cls, name, baseClasses): return {'meth':meth} def __new__(cls, name, baseClasses, classdict): return type.__new__(cls, name, baseClasses, classdict) class Test(metaclass = MyMeta): def __init__(self): pass attr = 'an attribute' t = Test() print(t.attr) |
我们从 PEP 3115 节选了一个更为有趣的例子,如清单 4 所示,这个例子创建了一个具有其方法名称列表的元类,而同时又保持了类方法声明的顺序。
# The custom dictionary class member_table(dict): def __init__(self): self.member_names = [] def __setitem__(self, key, value): # if the key is not already defined, add to the # list of keys. if key not in self: self.member_names.append(key) # Call superclass dict.__setitem__(self, key, value) # The metaclass class OrderedClass(type): # The prepare function @classmethod def __prepare__(metacls, name, bases): # No keywords in this case return member_table() # The metaclass invocation def __new__(cls, name, bases, classdict): # Note that we replace the classdict with a regular # dict before passing it to the superclass, so that we # don't continue to record member names after the class # has been created. result = type.__new__(cls, name, bases, dict(classdict)) result.member_names = classdict.member_names return result |
在元类内所做的这些改变有几个原因。对象的方法一般存储于一个字典,而这个字典是没有顺序的。不过,在某些情况下,若能保持所声明的类成员的顺序将非常有用。这可以通过让此元类在信息仍旧可用时,较早地涉入类的创建得以实现 — 这很有用,比如在 C 结构的创建中。借助这种新的机制还能在将来实现其他一些有趣的功能,比如在类构建期间将符号插入到所创建的类名称空间的主体以及对符号的前向引用。PEP 3115 提到更改语法还有美学方面的原因,但是对此尚存在无法用客观标准解决的争论(到 PEP 3115 的链接,请参见 参考资料)。
正如我在 Python 3 初探,第 1 部分:Python 3 的新特性 中提到的,ABC 是一些不能被实例化的类。Java 或 C++ 语言的程序员应该对此概念十分熟悉。Python 3 添加了一个新的框架 —abc— 它提供了对 ABC 的支持。
这个 abc 模块具有一个元类(ABCMeta
)和 修饰符(@abstractmethod
和 @abstractproperty
)。如果一个 ABC 具有一个@abstractmethod
或 @abstractproperty
,它就不能被实例化,但必须在一个子类内被覆盖。比如,如下代码:
>>>from abc import * >>>class C(metaclass = ABCMeta): pass >>>c = C() |
这些代码是可以的,但是不能像下面这样编码:
>>>from abc import * >>>class C(metaclass = ABCMeta): ... @abstractmethod ... def absMethod(self): ... pass >>>c = C() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class C with abstract methods absMethod |
更好的做法是使用如下代码:
>>>class B(C): ... def absMethod(self): ... print("Now a concrete method") >>>b = B() >>>b.absMethod() Now a concrete method |
ABCMeta
类覆盖属性 __instancecheck__
和 __subclasscheck__
,借此可以重载内置函数 isinstance()
和 issubclass()
。要向 ABC 添加一个虚拟子类,可以使用 ABCMeta
提供的 register()
方法。如下所示的简单示例:
>>>class TestABC(metaclass=ABCMeta): pass >>>TestABC.register(list) >>>TestABC.__instancecheck__([]) True |
它等同于使用 isinstance(list, TestABC)
。您可能已经注意到 Python 3 使用 __instancecheck__
,而非 __issubclass__
,使用__subclasscheck__
,而非 __issubclass__
,这看起来更为自然。若将参数 isinstance(subclass, superclass)
反转成,比如superclass.__isinstance__(subclass)
,可能会引起混淆。可见,语法 superclass.__instancecheck__(subclass)
显然更好一点。
在 collections
模块内,可以使用几个 ABC 来测试一个类是否提供了特定的一个接口:
>>>from collections import Iterable >>>issubclass(list, Iterable) True |
表 1 给出了这个集合框架的 ABC。
Container |
|
Hashable |
|
Iterable |
|
Iterator |
Iterable |
Sized |
|
Callable |
|
Sequence |
Sized , Iterable , Container
|
MutableSequence |
Sequence |
Set |
Sized , Iterable , Container
|
MutableSet |
Set |
Mapping |
Sized , Iterable , Container
|
MutableMapping |
Mapping |
MappingView |
Sized |
KeysView |
MappingView , Set
|
ItemsView |
MappingView , Set
|
ValuesView |
MappingView |
集合
集合框架包括容器数据类型、双端队列(即 deque)以及一个默认的字典(即 defaultdict
)。一个 deque 支持从前面或后面进行追加和弹出。defaultdict
容器是内置字典的一个子类,它(根据 Python 3 文档)“覆盖一个方法并添加一个可写的实例变量。”除此之外,它还充当一个字典。此外,集合框架还提供了一个数据类型工厂函数namedtuple()
。
Python 3 现支持能代表数值类的 ABC 的类型层次结构。这些 ABC 存在于 numbers
模块内并包括 Number
、 Complex
、Real
、 Rational
和Integral
。图 1 显示了这个数值层次结构。可以使用它们来实现您自己的数值类型或其他数值 ABC。
数值塔(numerical tower)
Python 的数值层次结构的灵感来自于 Scheme 语言的数值塔。
新模块 fractions
可实现这个数值 ABC Rational
。此模块提供对有理数算法的支持。若使用 dir(fractions.Fraction)
,就会注意到它具有一些属性,比如 imag
、 real
和 __complex__
。根据数值塔的原理分析,其原因在于 Rationals
继承自 Reals
,而 Reals
继承自 Complex
。
在 Python 3 内,except
语句已经被修改为处理语法不清的问题。之前,在 Python version 2.5 内,try . . . except
结构,比如:
>>>try: ... x = float('not a number') ... except (ValueError, NameError): ... print "can't convert type" |
可能会被不正确地写为:
>>> try: ... x = float('not a number') ... except ValueError, NameError: ... print "can't convert type" |
后一种格式的问题在于 ValueError
异常将永远捕获不到,因为解释器将会捕获 ValueError
并将此异常对象绑定到名称 NameError
。这一点可以从下面的示例中看出:
>>> try: ... x = float('blah') ... except ValueError, NameError: ... print "NameError is ", NameError ... NameError is invalid literal for float(): not a number |
所以,为了处理语法不清的问题,在想要将此异常对象与另一个名称绑定时,逗号(,
)会被替换成关键字 as
。如果想要捕获多个异常,必须使用括号(()
)。清单 5 中的代码展示了 Python 3 内的两个合乎语法的示例。
# bind ValueError object to local name ex try: x = float('blah') except ValueError as ex: print("value exception occurred ", ex) # catch two different exceptions simultaneously try: x = float('blah') except (ValueError, NameError): print("caught both types of exceptions") |
异常处理的另一个改变是异常链 — 隐式或显式。清单 6 给出了隐式异常链的一个示例。
def divide(a, b): try: print(a/b) except Exception as exc: def log(exc): fid = open('logfile.txt') # missing 'w' print(exc, file=fid) fid.close() log(exc) divide(1,0) |
divide()
方法试图执行除数为零的除法,因而引发了一个异常:ZeroDivisionError
。但是,在异常语句的嵌套 log()
方法内,print(exc, file=fid)
试图向一个尚未打开的文件进行写操作。Python 3 抛出异常,如清单 7 所示。
Traceback (most recent call last): File "chainExceptionExample1.py", line 3, in divide print(a/b) ZeroDivisionError: int division or modulo by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "chainExceptionExample1.py", line 12, in <module> divide(1,0) File "chainExceptionExample1.py", line 10, in divide log(exc) File "chainExceptionExample1.py", line 7, in log print(exc, file=fid) File "/opt/python3.0/lib/python3.0/io.py", line 1492, in write self.buffer.write(b) File "/opt/python3.0/lib/python3.0/io.py", line 696, in write self._unsupported("write") File "/opt/python3.0/lib/python3.0/io.py", line 322, in _unsupported (self.__class__.__name__, name)) io.UnsupportedOperation: BufferedReader.write() not supported |
请注意,这两个异常都被处理。在 Python 的早期版本中,ZeroDivisionError
将会丢失,得不到处理。那么这是如何实现的呢?__context__
属性,比如 ZeroDivisionError
,现在是所有异常对象的一部分。在本例中,被抛出的 IOError
的 __context__
属性 “仍为” __context__
属性内的 ZeroDivisionError
。
除 __context__
属性外,异常对象还有一个 __cause__
属性,它通常被初始化为 None
。这个属性的作用是以一种显式方法记录异常的原因。__cause__
属性通过如下语法设置:
>>> raise EXCEPTION from CAUSE |
它与下列代码相同:
>>>exception = EXCEPTION >>>exception.__cause__ = CAUSE >>>raise exception |
但更为优雅。清单 8 中所示的示例展示了显式异常链。
class CustomError(Exception): pass try: fid = open("aFile.txt") # missing 'w' again print("blah blah blah", file=fid) except IOError as exc: raise CustomError('something went wrong') from exc |
正如之前的例子所示,print()
函数抛出了一个异常,原因是文件尚未打开以供写入。清单 9 给出了相应的跟踪。
Traceback (most recent call last): File "chainExceptionExample2.py", line 5, in <module> fid = open("aFile.txt") File "/opt/python3.0/lib/python3.0/io.py", line 278, in __new__ return open(*args, **kwargs) File "/opt/python3.0/lib/python3.0/io.py", line 222, in open closefd) File "/opt/python3.0/lib/python3.0/io.py", line 615, in __init__ _fileio._FileIO.__init__(self, name, mode, closefd) IOError: [Errno 2] No such file or directory: 'aFile.txt' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "chainExceptionExample2.py", line 8, in <modulei> raise CustomError('something went wrong') from exc __main__.CustomError: something went wrong |
请注意,在异常跟踪中的一行 “The above exception was the direct cause of the following exception,” 之后的是另一个对导致CustomError
“something went wrong” 异常的跟踪。
添加给异常对象的另一个属性是 __traceback__
。如果被捕获的异常不具备其 __traceback__
属性,那么新的跟踪就会被设置。如下是一个简单的例子:
from traceback import format_tb try: 1/0 except Exception as exc: print(format_tb(exc.__traceback__)[0]) |
请注意,format_tb
返回的是一个列表,而且此列表中只有一个异常。
with 语句
从 Python 版本 2.6 开始,with
已经成为了一个关键字,而且这一属性无需再通过 __future__
导入。
Python 支持不同进制的整型字符串文本 — 八进制、十进制(最明显的!)和十六进制 — 而现在还加入了二进制。八进制数的表示已经改变:八进制数现在均以一个前缀 0o
或 0O
(即,数字零后跟一个大写或小写的字母 o)开头。比如,八进制的 13 或十进制的 11 分别如下表示:
>>>0o13 11 |
新的二进制数则以前缀 0b
或 0B
(即,数字零后跟一个大写或小写的字母 b)开头。十进制数 21 用二进制表示应为:
>>>0b010101 21 |
oct()
和 hex()
方法已被删除。
函数注释 会在编译时将表述与函数的某些部分(比如参数)相关联。就其本身而言,函数注释是无意义的 — 即,除非第三方库对之进行处理,否则它们不会被处理。函数注释的作用是为了标准化函数参数或返回值被注释的方式。函数注释语法为:
def methodName(param1: expression1, ..., paramN: expressionN)->ExpressionForReturnType: ...发表评论
-
老王的Python教程-推荐
2011-02-02 22:46 1969强烈推荐,适合入门,适合深入 http://www.cnpy ... -
转贴一篇不错的Python入门教程 - Instant Hacking[译文]
2011-02-02 00:09 1937原文 http://www.hetland.org/ ... -
python快速入门教程
2011-02-01 23:41 1939python所支持的数据类型:整型、长整型、布尔型 ... -
python入门教程:语句和语法
2011-02-01 23:40 2245注释(#): python中的注 ... -
python教程:安装python运行环境以及简单程序
2011-02-01 23:38 2555python3.0已推出,但据说很多库都不能用了,建议 ... -
利用Python抓取和解析网页(二)补充
2011-02-01 23:34 1993五、为HTML文档中的属性值添加引号 前面我们 ... -
利用Python抓取和解析网页(二)
2011-02-01 23:31 5684对搜索引擎、文件索引、文档转换、数据检索、站点备份或迁移等应 ... -
利用Python抓取和解析网页(一)
2011-02-01 23:25 8052对搜索引擎、文件索引、文档转换、数据检索、站点备份或迁移等应用 ... -
Google Python 视频教程
2011-01-04 08:39 1626Google Python Class Day 1 Part ... -
Django学习笔记(收藏)
2011-01-01 15:43 1035Django笔记1 Django笔记2 ... -
用Redis存储好友关系-python版
2011-01-01 11:56 1424这是一个用Redis存储好友关系的python下使用Redis ... -
Python正则表达式指南
2010-12-23 12:12 12901. 正则表达式基础 1.1. 简单介绍 正则表达 ... -
Python 3 初探,第 1 部分: Python 3 的新特性
2010-12-07 19:58 965转自:Cesar Otero 简介: Python 3 是 ...
相关推荐
##### 第一部分:初探Python - **第1章:编程基础与字符串**:介绍Python的基础知识,包括编程环境的搭建、基本的数据类型、变量以及字符串的操作方法。 - **第2章:数字与运算符**:详细介绍Python中的数值类型和...
#### Python 第25课:初探list - **知识点介绍**:介绍列表的基本概念和操作方法。 - **实操要点**:创建和操作列表,实现基本的数据存储功能。 #### Python 第26课:操作list - **知识点介绍**:进一步探讨列表的...
在计算机等级考试中,Python部分考察的是学生的编程基础、逻辑思维能力和问题解决能力。因此,教学过程中应注重培养学生的这些核心素养,而不仅仅是语言语法。 二、教学内容与考试大纲对接 教学内容应紧密围绕...
#### Python第25课:初探list - **知识点概述**:介绍列表数据类型的基础知识。 - **详细内容**:列表是一种有序的、可变的数据集合。可以通过方括号`[]`创建列表。列表支持多种操作,如索引、切片等。 #### Python...
#### 五、高级主题 - **【Python第55课】正则表达式(1)** 正则表达式是一种强大的文本处理工具。本课将介绍正则表达式的基础知识,包括元字符、字符类等。 - **【Python第56课】正则表达式(2)** 进一步...
"Python程序设计课程中的课堂思政元素初探"这个主题,旨在探讨如何在教授Python编程语言的同时,有效地引入思政教育,让学生在学习技术的同时,也能提升道德品质和社会责任感。 首先,Python是一种广泛使用的高级...
### OpenCV 学习资料文档知识点汇总 ...这部分内容涉及了直方图的相关概念和技术,以及如何利用直方图进行图像匹配等高级主题。由于提供的文档部分内容较短,无法全面覆盖该章节所有细节,但以上总结涵盖了关键知识点。
《Python for Data Science初探——基于Microsoft DAT208x课程》 在现代数据分析领域,Python语言已经成为不可或缺的工具,尤其在数据科学方面,它的强大功能和易用性深受广大用户的喜爱。Microsoft DAT208x课程...
《IADS-cw:爱丁堡大学算法与数据结构初探》 爱丁堡大学的IADS(Introduction to Algorithms and Data ...通过这些练习,学生可以掌握Python的高级特性和面向对象编程概念,为未来的学习和职业发展打下坚实基础。