python2和python3的区别,转换及共存

2025-02-24 18:14:35
推荐回答(1个)
回答1:

python2和python3的区别

1.性能

Py3.0运行 pystone benchmark的速度比Py2.5慢30%。Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好的优化结果。

Py3.1性能比Py2.5慢15%,还有很大的提升空间。 

2.编码 

Py3.X源码文件默认使用utf-8编码,这就使得以下代码是合法的: 
>>> 中国 = 'china' 
>>>print(中国) 
china

3. 语法

1)去除了<>,全部改用!= 

在Python 2里,为了得到一个任意对象的字符串表示,有一种把对象包装在反引号里(比如`x`)的特殊语法。在Python 3里,这种能力仍然存在,但是你不能再使用反引号获得这种字符串表示了。你需要使用全局函数repr()。

Notes

Python 2

Python 3

`x`    repr(x)    

`'PapayaWhip' + `2``    repr('PapayaWhip'+ repr(2))    

Note:x可以是任何东西 — 一个类,函数,模块,基本数据类型,等等。repr()函数可以使用任何类型的参数。

2)去除``,全部改用repr() 

3)关键词加入as 和with,还有True,False,None 

4)整型除法返回浮点数,要得到整型结果,请使用//

由于人们常常会忽视Python 3在整数除法上的改动(写错了也不会触发Syntax Error),所以在移植代码或在Python 2中执行Python 3的代码时,需要特别注意这个改动。

所以,我还是会在Python 3的脚本中尝试用float(3)/2或 3/2.0代替3/2,以此来避免代码在Python 2环境下可能导致的错误(或与之相反,在Python 2脚本中用from __future__ import division来使用Python 3的除法)。

Python 2

print '3 / 2 =', 3 / 2 print '3 // 2 =', 3 // 2 print '3 / 2.0 =', 3 / 2.0 print '3 // 2.0 =', 3 // 2.0 
3 / 2 = 1 3 // 2 = 1 3 / 2.0 = 1.5 3 // 2.0 = 1.0 

默认,如果两个操作数都是整数,Python 2 自动执行整型计算。

Python 3

print('3 / 2 =', 3 / 2) print('3 // 2 =', 3 // 2) print('3 / 2.0 =', 3 / 2.0) print('3 // 2.0 =', 3 // 2.0) 
3 / 2 = 1.5 3 // 2 = 1 3 / 2.0 = 1.5 3 // 2.0 = 1.0

Note: 需要注意的是“双划线”(//)操作符将一直执行整除,而不管操作数的类型,这就是为什么 5.0//2.0 值为 2.0。Python 3 中,/ 操作符是做浮点除法,而 // 是做整除(即商没有余数,比如 10 // 3 其结果就为 3,余数会被截除掉,而 (-7) // 3 的结果却是 -3。这个算法与其它很多编程语言不一样,需要注意,它们的整除运算会向0的方向取值。而在 Python 2 中,/ 就是整除,即和 Python 3 中的 // 操作符一样。

5)加入nonlocal语句。使用noclocal x可以直接指派外围(非全局)变量 

6)print

去除print语句,加入print()函数实现相同的功能。同样的还有 exec语句,已经改为exec()函数 

在Python 2里,print是一个语句。无论你想输出什么,只要将它们放在print关键字后边就可以。

Python 3里,print()是一个函数。就像其他的函数一样,print()需要你将想要输出的东西作为参数传给它。

例如: 
2.X: print "The answer is", 2*2 
3.X: print("The answer is", 2*2) 
2.X: print x, # 使用逗号结尾禁止换行 
3.X: print(x, end=" ") # 使用空格代替换行 

在Python 2里,如果你使用一个逗号(,)作为print语句的结尾,它将会用空格分隔输出的结果,然后在输出一个尾随的空格(trailing space),而不输出回车(carriage return)。在Python 3里,通过把end=' '作为一个关键字参数传给print()可以实现同样的效果。参数end的默认值为'\n',所以通过重新指定end参数的值,可以取消在末尾输出回车符。
2.X: print # 输出新行 
3.X: print() # 输出新行 
2.X: print >>sys.stderr, "fatal error" 
3.X: print("fatal error", file=sys.stderr) 

在Python 2里,你可以通过使用>>pipe_name语法,把输出重定向到一个管道,比如sys.stderr。在Python 3里,你可以通过将管道作为关键字参数file的值传递给print()来完成同样的功能。参数file的默认值为std.stdout,所以重新指定它的值将会使print()输出到一个另外一个管道。
2.X: print (x, y) # 输出repr((x, y)) 
3.X: print((x, y)) # 不同于print(x, y)!

exec语句

exec()函数使用一个包含任意Python代码的字符串作为参数,然后就像执行语句或者表达式一样执行它。exec()跟eval()是相似的,但是exec()更加强大并更具有技巧性。eval()函数只能执行单独一条表达式,但是exec()能够执行多条语句,导入(import),函数声明 — 实际上整个Python程序的字符串表示也可以。

Notes

Python 2

Python 3

exec codeString    exec(codeString)    

exec codeString in a_global_namespace    exec(codeString, a_global_namespace)    

exec codeString in a_global_namespace, a_local_namespace    exec(codeString, a_global_namespace, a_local_namespace)    

  • 在最简单的形式下,因为exec()现在是一个函数,而不是语句,2to3会把这个字符串形式的代码用括号围起来。

  • Python 2里的exec语句可以指定名字空间,代码将在这个由全局对象组成的私有空间里执行。Python 3也有这样的功能;你只需要把这个名字空间作为第二个参数传递给exec()函数。

  • 更加神奇的是,Python 2里的exec语句还可以指定一个本地名字空间(比如一个函数里声明的变量)。在Python 3里,exec()函数也有这样的功能。

  • execfile语句

    就像以前的exec语句,Python 2里的execfile语句也可以像执行Python代码那样使用字符串。不同的是exec使用字符串,而execfile则使用文件。在Python 3里,execfile语句已经被去掉了。如果你真的想要执行一个文件里的Python代码(但是你不想导入它),你可以通过打开这个文件,读取它的内容,然后调用compile()全局函数强制Python解释器编译代码,然后调用新的exec()函数。

    Notes

    Python 2

    Python 3

  • execfile('a_filename')    exec(compile(open('a_filename').read(),'a_filename','exec'))    
  • 7)输入函数改变了,删除了raw_input,用input代替: Python 2有两个全局函数,用来在命令行请求用户输入。第一个叫做input(),它等待用户输入一个Python表达式(然后返回结果)。第二个叫做raw_input(),用户输入什么它就返回什么。这让初学者非常困惑,并且这被广泛地看作是Python语言的一个“肉赘”(wart)。Python 3通过重命名raw_input()为input(),从而切掉了这个肉赘,所以现在的input()就像每个人最初期待的那样工作。
    2.X:guess = int(raw_input('Enter an integer : ')) # 读取键盘输入的方法 
    3.X:guess = int(input('Enter an integer : '))

    Note:如果你真的想要请求用户输入一个Python表达式,计算结果,可以通过调用input()函数然后把返回值传递给eval()。

    I/O方法xreadlines()

    在Python 2里,文件对象有一个xreadlines()方法,它返回一个迭代器,一次读取文件的一行。这在for循环中尤其有用。事实上,后来的Python 2版本给文件对象本身添加了这样的功能。

    在Python 3里,xreadlines()方法不再可用了。2to3可以解决简单的情况,但是一些边缘案例则需要人工介入。

    Notes

    Python 2

    Python 3

  • for line in a_file.xreadlines():    for line in a_file:    
  • for line in a_file.xreadlines(5):    no change (broken)    
  • 如果你以前调用没有参数的xreadlines(),2to3会把它转换成文件对象本身。在Python 3里,这种转换后的代码可以完成前同样的工作:一次读取文件的一行,然后执行for循环的循环体。

  • 如果你以前使用一个参数(每次读取的行数)调用xreadlines(),2to3不能为你完成从Python 2到Python 3的转换,你的代码会以这样的方式失败:AttributeError: '_io.TextIOWrapper' object has no attribute 'xreadlines'。你可以手工的把xreadlines()改成readlines()以使代码能在Python 3下工作。(readline()方法在Python 3里返回迭代器,所以它跟Python 2里的xreadlines()效率是不相上下的。)


  • 8)改变了顺序操作符的行为,例如x

    9)去除元组参数解包。不能def(a, (b, c)):pass这样定义函数了

    10)新式的8进制字变量,相应地修改了oct()函数。
    2.X的方式如下: 
    >>> 0666 
    438 
    >>> oct(438) 
    '0666'


    3.X这样: 
    >>> 0666 
    SyntaxError: invalid token (, line 1) 
    >>> 0o666 
    438 
    >>> oct(438) 
    '0o666'

    11)增加了 2进制字面量和bin()函数 
    >>> bin(438) 
    '0b110110110' 
    >>> _438 = '0b110110110' 
    >>> _438 
    '0b110110110'

    12)扩展的可迭代解包。在Py3.X 里,a, b, *rest = seq和 *rest, a = seq都是合法的,只要求两点:rest是list对象和seq是可迭代的。

    13)新的super(),可以不再给super()传参数,
    >>> class C(object): 
    def __init__(self, a): 
    print('C', a) 
    >>> class D(C): 
    def __init(self, a): 
    super().__init__(a) # 无参数调用super() 
    >>> D(8) 
    C 8 
    <__main__.D object at 0x00D7ED90>

    14)支持class decorator。用法与函数decorator一样:
    >>> def foo(cls_a): 
    def print_func(self): 
    print('Hello, world!') 
    cls_a.print = print_func 
    return cls_a 
    >>> @foo 
    class C(object): 
    pass 
    >>> C().print() 
    Hello, world! 

    class decorator可以用来玩玩狸猫换太子的大把戏。更多请参阅PEP 3129

    4. 字符串和字节串 

    Python 2有两种字符串类型:Unicode字符串和非Unicode字符串。Python 2有基于ASCII的str()类型,其可通过单独的unicode()函数转成unicode类型,但没有byte类型。

    而在Python 3中,终于有了Unicode(utf-8)字符串,以及两个字节类:bytes和bytearrays。Python 3只有一种类型:Unicode字符串(Unicode strings)。只有str一种类型,但它跟2.x版本的unicode几乎一样。

    Notes

    Python 2

    Python 3

  • u'PapayaWhip'    'PapayaWhip'    
  • ur'PapayaWhip\foo'    r'PapayaWhip\foo'    
  • Python 2里的Unicode字符串在Python 3里即普通字符串,因为在Python 3里字符串总是Unicode形式的。

  • Unicode原始字符串(raw string)(使用这种字符串,Python不会自动转义反斜线"\")也被替换为普通的字符串,因为在Python 3里,所有原始字符串都是以Unicode编码的。

  • 全局函数unicode()

    Python 2有两个全局函数可以把对象强制转换成字符串:unicode()把对象转换成Unicode字符串,还有str()把对象转换为非Unicode字符串。

    Python 3只有一种字符串类型,Unicode字符串,所以str()函数即可完成所有的功能。(unicode()函数在Python 3里不再存在了。)

    Notes

    Python 2

    Python 3

  • unicode(anything)    str(anything)    

  • 5.数据类型 

    1)Python 2有为非浮点数准备的int和long类型。int类型的最大值不能超过sys.maxint,而且这个最大值是平台相关的。可以通过在数字的末尾附上一个L来定义长整型,显然,它比int类型表示的数字范围更大。

    在Python 3里,只有一种整数类型int,大多数情况下,它很像Python 2里的长整型。

    Note:检查一个变量是否是整型,获得它的数据类型,并与一个int类型(不是long)的作比较。你也可以使用isinstance()函数来检查数据类型;再强调一次,使用int,而不是long,来检查整数类型。

    sys.maxint

    由于长整型和整型被整合在一起了,sys.maxint常量不再精确。但是因为这个值对于检测特定平台的能力还是有用处的,所以它被Python 3保留,并且重命名为sys.maxsize。

    Notes

    Python 2

    Python 3

  • from sys import maxint    from sys import maxsize