码修
2019 年 6 月 14 日
格式化字符串 f-strings (3.6+)
将变量组合成符串输出, 是任何一门语言都要碰到的问题, python 2 以前是这么处理的:
- user = "Jane Doe"
- action = "buy"
- log_message = 'User {} has logged in and did an action {}.'.format(
- user,
- action
- )
- print(log_message)
- # User Jane Doe has logged in and did an action buy.
与 python 2 的 format 方法不同, python 3 提供了 f-strings 的方法:
- user = "Jane Doe"
- action = "buy"
- log_message = f'User {user} has logged in and did an action {action}.'
- print(log_message)
- # User Jane Doe has logged in and did an action buy.
真香!
Pathlib (3.4+)
python 3 提供的 Pathlib 文件路径包比 os.path() 好用多了, 如果你不太了解这个类库, 请查看: Why you should be using pathlib - Trey Hunner:
- from pathlib import Path
- root = Path('post_sub_folder')
- print(root)
- # post_sub_folder
- path = root / 'happy_user'
- # Make the path absolute
- print(path.resolve())
- # /home/weenkus/Workspace/Projects/DataWhatNow-Codes/how_your_python3_should_look_like/post_sub_folder/happy_user
类型提示 Type hinting (3.5+)
众所周知, Python 是动态类型语言, 运行时不需要指定变量类型. Python 的主要卖点之一就是它是动态类型的, 这一点也不会改变. 而在 2014 年 9 月, Guido van Rossum (Python BDFL) 创建了一个 Python 增强提议 (PEP-484), 为 Python 添加类型提示 (Type Hints), 写不写你自己看着办喽:
- # 变量注解
- a: int = 5
- b: bool = True
- f: float = 5.0
- s: str = "abc"
- # 函数注解
- def sentence_has_animal(sentence: str) -> bool:
- return "animal" in sentence
- sentence_has_animal("Donald had a farm without animals")
- # True
内置枚举类型 Enumerations (3.4+)
Python 3 可以通过 Enum 类型非常方便的创建枚举类型:
- from enum import Enum, auto
- class Monster(Enum):
- ZOMBIE = auto()
- WARRIOR = auto()
- BEAR = auto()
- print(Monster.ZOMBIE)
- # Monster.ZOMBIE
- for monster in Monster:
- print(monster)
- # Monster.ZOMBIE
- # Monster.WARRIOR
- # Monster.BEAR
- Built-in LRU cache (3.2+)
LRU (Least Recently Used) 是缓存置换策略中的一种常用的算法. 当缓存队列已满时, 新的元素加入队列时, 需要从现有队列中移除一个元素, LRU 策略就是将最近最少被访问的元素移除, 从而腾出空间给新的元素.
下面是一个斐波纳契函数的实现, 将让你看到缓存机制带来的好处:
- import time
- def fib(number: int) -> int:
- if number == 0: return 0
- if number == 1: return 1
- return fib(number-1) + fib(number-2)
- start = time.time()
- fib(40)
- print(f'Duration: {time.time() - start}s')
- # Duration: 30.684099674224854s
现在我们用 lru_cache 缓存机制来优化以上代码:
- from functools import lru_cache
- @lru_cache(maxsize=512)
- def fib_memoization(number: int) -> int:
- if number == 0: return 0
- if number == 1: return 1
- return fib_memoization(number-1) + fib_memoization(number-2)
- start = time.time()
- fib_memoization(40)
- print(f'Duration: {time.time() - start}s')
- # Duration: 6.866455078125e-05s
数量可变的位置参数 Extended iterable unpacking (3.0+)
官方文档: PEP 3132 - Extended Iterable Unpacking | Python.org https://www.python.org/dev/peps/pep-3132/
- head, *body, tail = range(5)
- print(head, body, tail)
- # 0 [1, 2, 3] 4
- py, filename, *cmds = "python3.7 script.py -n 5 -l 15".split()
- print(py)
- print(filename)
- print(cmds)
- # python3.7
- # script.py
- # ['-n', '5', '-l', '15']
- first, _, third, *_ = range(10)
- print(first, third)
- # 0 2
数据类 Data classes (3.7+)
Python 3 引入了数据类型类, 这样你在新建数据模型时不用写__init__() and __repr()__等方法. 如果, python 2:
- class Armor:
- def __init__(self, armor: float, description: str, level: int = 1):
- self.armor = armor
- self.level = level
- self.description = description
- def power(self) -> float:
- return self.armor * self.level
- armor = Armor(5.2, "Common armor.", 2)
- armor.power()
- # 10.4
- print(armor)
- # <__main__.Armor object at 0x7fc4800e2cf8>
而在 python 3 中
- from dataclasses import dataclass
- @dataclass
- class Armor:
- armor: float
- description: str
- level: int = 1
- def power(self) -> float:
- return self.armor * self.level
- armor = Armor(5.2, "Common armor.", 2)
- armor.power()
- # 10.4
- print(armor)
- # Armor(armor=5.2, description='Common armor.', level=2)
隐式命名空间包 Implicit namespace packages (3.3+)
以前创建名称空间包时, python 2 是这样的:
- sound/ Top-level package
- __init__.py Initialize the sound package
- formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
- ...
- effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
- ...
- filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
以上每个文件夹里都会有一个 __init__.py 的文件, 这个文件会让这个文件夹被 python 识别为 packages. 而 python 3.3 引入了 PEP 420 - Implicit Namespace Packages | Python.org https://www.python.org/dev/peps/pep-0420/ , 不再需要这个文件.
- sound/ Top-level package
- __init__.py Initialize the sound package
- formats/ Subpackage for file format conversions
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
- ...
- effects/ Subpackage for sound effects
echo.py
surround.py
reverse.py
- ...
- filters/ Subpackage for filters
equalizer.py
vocoder.py
karaoke.py
...
来源: http://www.mzh.ren/things-you-are-probably-not-using-in-python-3-but-should.html