python2.0和3.0区别 2.5.1 与python2.0和3.0区别 3.0 有什么区别? (详细代码)

IBM Bluemix
点击按钮,开始云上的开发!
developerWorks 社区
Python 3 是 Guido van Rossum 功能强大的通用编程语言的最新版本。它虽然打破了与 2.x 版本的向后兼容性,但却清理了某些语法方面的问题。本文是这个由两部分组成的系列文章中的第二篇,本文构建在此系列
的基础之上,内容涵盖了 Python 更多的新特性和更高深的一些主题,比如在抽象基类、元类和修饰符等方面的变化。
, 顾问, 自由职业
Cesar Otero 是一名 Java 和 Python 顾问。他具有电气工程学位并兼修了数学。
—,也即 Python 3000 或 Py3K— 的前一篇文章讨论了 Python 内打破向后兼容性的一些基本变化,比如新的 print() 函数、
bytes 数据类型以及
string 类型的变化。本文是该系列文章的第 2 部分,探究了更为高深的一些主题,比如抽象基类(ABC)、元类、函数注释和修饰符(decorator)、整型数(integer literal)支持、数值类型层次结构以及抛出和捕获异常,其中的大多数特性仍然会打破与版本 2x 产品线的向后兼容性。 类修饰符在 Python 之前的版本中,对方法的转换必须在方法定义之后进行。对于较长的方法,此要求将定义的重要组成部分与 Python Enhancement
Proposal (PEP) 318(有关链接,请参见 )给出的外部接口定义分离。下面的代码片段演示了这一转换要求:清单 1. Python 3 之前版本中的方法转化def myMethod(self):
# do something
myMethod = transformMethod(myMethod)为了让此类情景更易于读懂,也为了避免必须多次重用相同的方法名,在 Python 版本 2.4 中引入了方法修饰符。修饰符 是一些方法,这些方法可以修改其他方法并返回一个方法或另外一个可调用对象。对它们的注释是在修饰符的名称前冠以 “at” 符号(@)— 类似 Java™ 注释的语法。清单 2 显示了实际应用中的修饰符。清单 2. 一个修饰符方法@transformMethod
def myMethod(self):
# do something修饰符是一些纯粹的语法糖(syntactic sugar)— 或者(如 Wikipedia 所言)“对计算机语言语法的补充,这些补充并不影响语言的功能,而是会让语言变得更易于被人使用。”修饰符的一种常见用法是注释静态方法。比如,清单 1 和清单 2 相当,但清单 2 更容易被人读懂。定义修饰符与定义其他方法无异:def mod(method):
method.__name__ = "John"
return method
def modMe():
print(modMe.__name__)更棒的是 Python 3 现在不仅支持针对方法的修饰符,并且支持针对类的修饰符,所以,取代如下的用法:class myClass:
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)注意:如果上面两个例子起不到任何作用,我强烈建议您阅读 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):
attr = 'an attribute'
t = Test()
print(t.attr)我们从 PEP 3115 节选了一个更为有趣的例子,如清单 4 所示,这个例子创建了一个具有其方法名称列表的元类,而同时又保持了类方法声明的顺序。清单 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 的链接,请参见
)。抽象基类正如我在
中提到的,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):
&&&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 methodABCMeta 类覆盖属性
__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。表 1. 这个集合框架的 ABCABCInheritsContainerHashableIterableIteratorIterableSizedCallableSequenceSized,
ContainerMutableSequenceSequenceSetSized,
ContainerMutableSetSetMappingSized,
ContainerMutableMappingMappingMappingViewSizedKeysViewMappingView,
SetItemsViewMappingView,
SetValuesViewMappingViewABC 类型层次结构Python 3 现支持能代表数值类的 ABC 的类型层次结构。这些 ABC 存在于 numbers 模块内并包括 Number、
Complex、Real、
Rational 和
Integral。图 1 显示了这个数值层次结构。可以使用它们来实现您自己的数值类型或其他数值 ABC。图 1. 数值层次结构 新模块 fractions 可实现这个数值
ABC Rational。此模块提供对有理数算法的支持。若使用
dir(fractions.Fraction),就会注意到它具有一些属性,比如 imag、
__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 内的两个合乎语法的示例。清单 5. Python 3 内的异常处理# bind ValueError object to local name ex
x = float('blah')
except ValueError as ex:
print("value exception occurred ", ex)
# catch two different exceptions simultaneously
x = float('blah')
except (ValueError, NameError):
print("caught both types of exceptions")异常处理的另一个改变是异常链— 隐式或显式。清单 6 给出了隐式异常链的一个示例。清单 6. Python 3 内的隐式异常链def divide(a, b):
print(a/b)
except Exception as exc:
def log(exc):
fid = open('logfile.txt') # missing 'w'
print(exc, file=fid)
fid.close()
divide(1,0)divide() 方法试图执行除数为零的除法,因而引发了一个异常:ZeroDivisionError。但是,在异常语句的嵌套 log() 方法内,print(exc, file=fid) 试图向一个尚未打开的文件进行写操作。Python 3 抛出异常,如清单 7 所示。清单 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
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 中所示的示例展示了显式异常链。清单 8. Python 3 中的显式异常链class CustomError(Exception):
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 给出了相应的跟踪。清单 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
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
except Exception as exc:
print(format_tb(exc.__traceback__)[0])请注意,format_tb 返回的是一个列表,而且此列表中只有一个异常。整数支持和语法 Python 支持不同进制的整型字符串文本 — 八进制、十进制(最明显的!)和十六进制 — 而现在还加入了二进制。八进制数的表示已经改变:八进制数现在均以一个前缀
0o 或 0O(即,数字零后跟一个大写或小写的字母 o)开头。比如,八进制的 13 或十进制的 11 分别如下表示:&&&0o13
11新的二进制数则以前缀
0b 或 0B(即,数字零后跟一个大写或小写的字母 b)开头。十进制数 21 用二进制表示应为:&&&0b010101
21oct() 和 hex()
方法已被删除。函数注释函数注释 会在编译时将表述与函数的某些部分(比如参数)相关联。就其本身而言,函数注释是无意义的 — 即,除非第三方库对之进行处理,否则它们不会被处理。函数注释的作用是为了标准化函数参数或返回值被注释的方式。函数注释语法为:def methodName(param1: expression1, ..., paramN: expressionN)-&ExpressionForReturnType:
...例如,如下所示的是针对某函数的参数的注释:def execute(program:"name of program to be executed", error:"if something goes wrong"):
...如下的示例则注释了某函数的返回值。这对于检查某函数的返回类型非常有用:def getName() -& "isString":
...函数注释的完整语法可以在 PEP 3107(相关链接,请参见
)内找到。结束语Python 3 最终的发布版在 2008 年 12 月份初就已经发布。自那之后,我曾经查阅过一些博客,试图了解人们对向后不兼容性问题的反应。虽然,我不能断言社区在某些程度上已经达成了官方的共识,但我阅读过的博客所呈现的观点呈两极分化。Linux® 开发社区似乎不太喜欢转变到版本 3,因为需要移植大量代码。相比之下,因为新版本对 unicode 支持方面的改进,很多 Web 开发人员则欢迎转变。我想要说明的一点是,在您做决定是否要移植到新版本之前,应该仔细阅读相关的 PEP 和开发邮件列表。这些 PEP 解释了各项更改的初衷、带来的益处及其实现。不难看出,这些更改的做出经过了深思熟虑和激烈讨论。本系列所展示的这些主题旨在让普通的 Python 程序员无需遍阅所有的 PEP 就能立即对这些更改有大致的概念。
参考资料 请先阅读这个由两部分组成的系列文章的第 1 部分:
阅读 Python 3 的相关 PEP:
:Decorators for Functions and Methods:Function Annotations:Class Decorators:Integer Literal Support and Syntax:Metaclasses in Python 3000:Introducing Abstract Base Classes:A
Type Hierarchy for Numbers:Raising Exceptions in Python 3000:Catching Exceptions in Python 3000:Keyword-Only Arguments 阅读 Wikipedia 有关
阅读 David Mertz 和 Michele Simionato 合写的
developerWorks 系列文章
(developerWorks,2003 年 2 月)。
Wikipedia 提供了有关
的详细解释。
获得最新的
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
IBM PureSystems(TM) 系列解决方案是一个专家集成系统
通过学习路线图系统掌握软件开发技能
软件下载、试用版及云计算
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Linux, Open sourceArticleID=386783ArticleTitle=Python 3 初探,第 2 部分: 高级主题publish-date=python3x和python2x的区别,32位和64位的区别,微单和单反的区别,凤梨和菠萝的区别,..
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
python3x和python2x的区别
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口Python学习大本营
翻译文档列表

我要回帖

更多关于 python代码运行助手 的文章

 

随机推荐