What's New in Python 3.4
很震惊的发现时至今日,还有大批的人在使用 Python 2.x 构建项目,甚至还有很多人在构建新项目时依然选择使用 Python 2.x。
基本来说,只有三种情况阻止你使用 Python 3:
对于第一种,如果是大型项目,那就继续维护吧,小型项目的话,可以考虑用 Python 3 兼容的库进行重构。
第二种情况的话,不用担心,这篇文章就是给你打下基础的。
至于第三种,你还是认真去读下书吧。
这篇文章希望能简要的介绍一下 Python 3 的一些特性,帮你打开 Python 3 的大门,让你可以放心大胆的开始 Python 3 之路。
本文以 Python 3.4 和 Python 2.7 做对照说明,毕竟这是目前使用最多的两个版本(3.5 又有较大的改动,以后会另发一篇)。
一、变化
首先介绍一下 Python 3 相对于 Python 2 的一些变化,也是你不得不注意并记下的关键知识点。
1、编码
在 Python 2 里编码是一个让人相当头疼的东西,首先是源文件编码不统一,然后是 Python 解释器运行时的字节流编码不统一(由操作系统而定)。
对于使用 cp936 的中国用户而言,首先是代码里不能打中文,再次就是中文字符的处理很头大,以至于每当我们新建一个 .py 文件,首先就是复制粘贴这几行:
#! /usr/bin/env python# -*- coding: utf-8from __future__ import unicode_literals
# -*- coding: utf-8指定源文件编码为 utf8,然后用from __future__ import unicode_literals告诉 Python 用 unicode 作为默认字符串编码。
而在 Python 3 里,你再也不会见到这些东西了:
我们在 Python 2 内判断一个变量是否是字符串时,会这么写:
# PY2string = u'123'# 判断变量 string 是不是 strisinstance(string, str) # False# 判断变量 string 是不是 unicodeisinstance(string, unicode)# True# 判断变量 string 是不是 str 或 unicodeisinstance(string, basestring) # True
而在 Python 3 内,没有u'123'这个写法,直接写'123'就是 unicode:
# PY3string = '123'# 已经没有 basestring 和 unicode 这样的关键字isinstance(string, str)# True
在 Python 2 里,我们可以用decode将str转换为unicode,而在 Python 3 里,我们可以用encode将str转换为bytes。
# PY2type('123'.decode('utf8'))# unicode
# PY3type('123'.encode('utf8'))# bytes
2、除法
在 Python 2 里,除法默认是整除,会返回一个整数,而在 Python 3 里,除法会返回一个浮点数。
# PY21 / 2# 0
# PY31 / 2# 0.51 // 2# 0
我们可以在 Python 2 里使用from __future__ import division来模拟这一行为。
3、生成器
在 Python 3 里,keys, values, items, map, filter等方法都默认返回一个生成器,而不是像 Python 2 里直接返回 list,生成器在你需要的时候才去计算求值,可以极大的节约内存和提高响应速度。
# PY2d = {1: 2}d.items()# [(1, 2)] 直接以列表形式返回了结果
# PY3d = {1: 2}dv = d.items()dv# dict_items([(1, 2)])d.update({2: 3})dv# 原数据更新后,view 会同步更新# dict_items([(1, 2), (2, 3)])
其实准确的说返回的是一个 view,view 关联到原数据,当原始数据更新时,view 也会同步更新,而且只有在迭代时才会求值。
二、新语法
Python 3 内还引入了不少全新的语法。
1、迭代展开
PEP 3132
Python 3 中引入了一种新的写法,可以在变量名前加*来对数据进行展开,在需要拆解赋值一个很大的数组或生成器时,可以极大的减少代码量。
# PY3arr = [1, 2, 3, 4]# 可以用 * 做展开a, *b = arr# a = 1# b = [2, 3, 4]a, *b, c = arr# a = 1# b = [2, 3]# c = 4
2、强制命名参数
当一个函数有很多的命名参数时,我们在调用的时候必须要严格的按照顺序一一对应:
def myFunc(arg1, arg2, arg3):
pass# 必须按照参数顺序一个个的传入,很容易出错myFunc(val1, val2, val3)# 另一个好的调用习惯是用参数名传入myFunc(arg1=val1, arg2=val2, arg3=val3)
但是写程序不能光靠习惯吧,Python 3 让我们可以强迫函数调用必须使用命名参数,方法就是在需要强制使用命名的参数前加*:
def myFunc(*, arg1, arg2, arg3):
passmyFunc(1, 2, 3)# 报错# TypeError: myFunc() takes 0 positional arguments but 3 were givenmyFunc(arg1=1, arg2=2, arg3=3)# 必须显式命名调用
3、参数注释
PEP 3107
Python 3 里可以在函数定义时,对函数的参数和返回值编写注释,注释可以是任意 Python 对象和表达式。
比如说,我们可以合法的编写下面这个『变态』的函数:
# 函数注释可以用字符串、表达式和类型def anno_demo(
first_arg: '第一个参数',
sec_arg: 3 3,
*third_arg: list) -
|