在命令行中查询的方法是:
- $ python --version
- Python 3.9.0rc2
- $ python -V
- Python 3.9.0rc2
在执行代码过程中,也可以查询:
- >>> print(sys.version_info)
- sys.version_info(major=3, minor=9, micro=0, releaselevel='candidate', serial=2)
- >>> print(sys.version)
- 3.9.0rc2 (tags/v3.9.0rc2:2bd31b5, Sep 17 2020, 00:37:38) [MSC v.1927 32 bit (Intel)]
空格相关:
命名相关:
表达式和语句相关:
引入相关:
bytes 和 str 都可以表示字符序列。
bytes 实例包含的是原始数据,即 8 位的无符号值(通常按照 ASCII 编码标准来显示)。
- >>> a = b'h\x65llo'
- >>> print(list(a))
- [104, 101, 108, 108, 111]
- >>> print(a)
- b'hello'
str 实例包含的是 Unicode 码点,这些码点与人类语言之中的文本字符相对应。
- >>> a = 'a\u0300 propos'
- >>> print(list(a))
- ['a', '̀', ' ', 'p', 'r', 'o', 'p', 'o', 's']
- >>> print(a)
- à propos
要把 Unicode 数据转换成二进制数据,必须调用 str 的 encode 方法;要把二进制数据转换成 Unicode 数据,必须调用 bytes 的 decode 方法。
两个好用的辅助函数,在两种情况之间进行转换:
- def to_str(bytes_or_str):
- if isinstance(bytes_or_str, bytes):
- value = bytes_or_str.decode('utf-8')
- else:
- value = bytes_or_str
- return value
- def to_bytes(bytes_or_str):
- if isinstance(bytes_or_str, str):
- value = bytes_or_str.encode('utf-8')
- else:
- value = bytes_or_str
- return value
可以用 + 操作符将 bytes 添加到 bytes,str 也可以这样。但不能将 bytes 添加到 str,反之亦然。bytes 可以用二元操作符与 bytes 进行比较,str 与 str 之间也可以,但 bytes 与 str 不行。这两种实例不能在某些操作符(例如 >、==、+、%)上面混用。从文件中读取二进制数据(或写入二进制数据到文件),应该使用 'wb' 或 'rb' 这样的二进制模式打开文件。如果要从文件中读取的是 Unicode 数据,必须注意系统默认的文本编码方案,若无法肯定,可通过 encoding 参数明确指出。
这种语法要求在格式字符串的前面加上字母 f 作为前缀。
- >>> key = 'my_var'
- >>> value = 1.234
- >>> formatted = f'{key} = {value}'
- >>> print(formatted)
- my_var = 1.234
可以通过 ! 符号把值转化成 Unicode 及 repr 形式的字符串:
- >>> formatted = f'{key!r:<10} = {value:.2f}'
- >>> print(formatted)
- 'my_var' = 1.23
要把 URL 中的查询字符串拆分成键值对,只需要使用 parse_qs 函数就可以了:
- >>> from urllib.parse import parse_qs
- >>> my_values = parse_qs('red=5&blue=0&green=', keep_blank_values=True)
- >>> print(repr(my_values))
- {'red': ['5'], 'blue': ['0'], 'green': ['']}
可以发现,有的参数可能带有多个值,有的参数可能只有一个值,有的参数可能是空白值,也会遇到根本没提供这个参数的情况。如果能把参数缺失与参数为空白值这两种情况都默认当成 0 就更好了。
- def get_first_int(values, key, default=0):
- found = values.get(key, [''])
- if found[0]:
- return int(found[0])
- return default
tuple 可以用不可变的序列把许多元素依次保存起来。
- >>> snack_calories = {
- 'chips': 140,
- 'popcorn': 80,
- 'nuts': 190,
- }
- >>> items = tuple(snack_calories.items())
- >>> print(items)
- (('chips', 140), ('popcorn', 80), ('nuts', 190))
可以用整数作下标,通过下标访问元组里边对应的元素:
- >>> item = ('Peanut butter', 'Jelly')
- >>> first = item[0]
- >>> second = item[1]
- >>> print(first, 'and', second)
- Peanut butter and Jelly
还可以使用一种更好的方法,叫作“拆分”。这种方法可以把元组中的元素分别赋给多个变量。
- >>> first, second = item
- >>> print(first, 'and', second)
- Peanut butter and Jelly
通过拆分来赋值要比通过下标访问元组内的元素更清晰,而且这种写法所需的代码量通常比较少。赋值操作的左边除了可以罗列单个变量,也可以写成列表、序列或任意深度的可迭代对象(iterable)。也可以原地交换两个变量,而不需要创建临时变量。
- def bubble_sort(a):
- for _ in range(len(a)):
- for i in range(1, len(a)):
- if a[i] < a[i-1]:
- a[i-1], a[i] = a[i], a[i-1]
拆分机制还有一个重要的用法,就是可以在 for 循环(或类似的结构)中把复杂的数据拆分到相关的变量之中:
- >>> snacks = [('bacon', 350), ('donut', 240), ('muffin', 190)]
- >>> for rank, (name, calories) in enumerate(snacks, 1):
- print(f'#{rank}: {name} has {calories} calories')
-
-
- #1: bacon has 350 calories
- #2: donut has 240 calories
- #3: muffin has 190 calories
拆分机制可以用在许多方面,例如构建列表(13)、给函数设计参数列表(22)、传递关键字参数(23)、接受多个返回值(19)等。
enumerate 是 Python 的 内置函数,它能把任意一种迭代器(iterator)封装成惰性生成器。这样每次循环的时候只需要从 iterator 里获取下一个值就行了,同时还会给出本轮循环的序号,即生成器每次产生的一对输出值。
- >>> flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']
- >>> it = enumerate(flavor_list)
- >>> print(next(it))
- (0, 'vanilla')
- >>> print(next(it))
- (1, 'chocolate')
- >>> for i, flavor in enumerate(flavor_list):
- print(f'{i+1}: {flavor}')
-
-
- 1: vanilla
- 2: chocolate
- 3: pecan
- 4: strawberry
- >>> for i, flavor in enumerate(flavor_list, 1):
- print(f'{i}: {flavor}')
-
-
- 1: vanilla
- 2: chocolate
- 3: pecan
- 4: strawberry
zip 函数可以把两个或更多的 iterator 封装成惰性生成器。每次循环时,它会分别从这些迭代器里获取各自的下一个元素,并把这些值放在一个元组里面。
- longest_name = None
- max_count = 0
- for name, count in zip(names, counts):
- if count > max_count:
- longest_name = name
- max_count = count
- >>> print(longest_name)
- Cecilia
- >>> print(max_count)
- 7
如果迭代器的长度不一致,只要其中任意一个迭代器处理完毕,就不再继续处理了。这时可以用 itertools.zip_longest 函数。
只有在整个循环没有因为 break 提前跳出的情况下,else 块才会执行。
使用海象表达式 :=
比如有几种水果要做成果汁,顾客点柠檬汁之前,要先确认现在还有没有柠檬可以榨汁,所以要先查出柠檬的数量,然后判断是不是非零的值:
- if count := fresh_fruit.get('lemon', 0):
- make_lemonade(count)
- else:
- out_of_stock()
如果是苹果汁,每杯果汁需要 4 颗苹果,可以这么写:
- if (count := fresh_fruit.get('apple', 0)) >= 4:
- make_lemonade(count)
- else:
- out_of_stock()