由于Python的版本更迭,很多人将自己的Python版本从2换成了3。这两个版本中,有一个非常出名的改变之一是: Python 2中的 print 函数被 Python 3中的 print()函数所代替。但是,如果在print关键字之后添加空格,则括号会在Python 2中起作用,因为解释器会将其视为表达式。 下面,我介绍一些令人吃惊的功能,这些功能只有在Python 3中才能找到。
以下所有示例均使用python 3.8.0进行编码,并且对于该算法,每个功能都涉及最低要求的Python版本我都标注出来了,觉得有用的同学请自觉收藏!
1.f字串(3.6+)
没有字符串的任何编程语言,都很难运行起来。可能你希望使用结构化的方法来处理字符串以保持高效,但是大多数使用Python的人更喜欢使用format方法。
user = “Amritansh”
action = “coding”
log_message = ‘User {} has logged in and did an action {}.’.format(
user,
action
)
print(log_message)
# 用户Amritansh已登录并执行了操作编码
除了 format 方法外,python3 还提供了一种通过 f-strings 插值字符串的通用方法。它与上面使用f字符串的代码相同:
user = “Amritansh”
action = “coding”
log_message = f’User {user} has logged in and did an action {action}.’
print(log_message)
# 用户Amritansh已登录并执行了操作编码
2.Pathlib(3.4+)
f字符串是难以置信的,但是像文件路径这样的字符串有自己的库,那就可以更容易地操作它们了。作为处理文件路径的方便抽象,Python3提供了pathlib。
from pathlib import Path
root = Path(‘post_sub_folder’)
print(root)
# 后置子文件夹
path = root / ‘hAppy_user’
#使路径绝对化
print(path.resolve())
# /home/weenkus/Workspace/Projects/DataWhatNow- Codes/how_your_python3_should_look_like/post_sub_folder/happy_user
3.类型提示(3.5+)
相对于动态类型而言,静态与动态类型是软件工程领域的热门话题,并且每个人对此都有自己的见解。程序员可以自己决定应该何时编写类型,但是我觉得你至少应该知道python3中支持的类型提示。
def sentence_has_animal(sentence: str) -> bool:
return “animal” in sentence
sentence_has_animal(“Donald had a farm without animals”)
# True
4.枚举(3.4+)
Python 3提供了一种简单的方法来在Enum类中编写枚举。 枚举是封装常量列表的有用方法,因此在没有太多结构的情况下,它们不会在代码中随机出现。
from enum import Enum, auto
class Monster(Enum):
ZOMBIE = auto()
WARRIOR = auto()
BEAR = auto()
print(Monster.ZOMBIE)
# Monster.ZOMBIE
枚举是一组绑定到唯一常量值的符号名(成员)。在枚举中,成员可以通过标识进行比较,并且可以迭代枚举本身。
枚举官方文档:https://docs.python.org/3/library/enum.html
for monster in Monster:
print(monster)
# Monster.ZOMBIE
# Monster.WARRIOR
# Monster.BEAR
5.内置LRU缓存(3.2+)
我们今天使用的软件和硬件,基本上每个水平切片中,都存在缓存。python3通过将LRU(最近已经很少使用)缓存作为一个称为LRU cache的装饰器,使其使用变得非常简单。
从缓存中受益的有基本的Fibonacci函数,因其在递归过程中,多次执行相同的任务。
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’)
# 持续时间: 30.684099674224854s
现在我们可以使用 LRU 缓存来配置它(这种优化技术称为记忆化)。可以让运行时间从秒降低到纳秒。
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’)
# 持续时间: 6.866455078125e-05s
6.扩展的iterable拆包(3.0+)
官方文档在这里: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
7.数据类别(3.7+)
Python 3 提供的数据类几乎没有什么限制,并且由于装饰器会自动生成特殊的方法(例如¼__init__()和__repr __()),因此可用于减少样板代码。 在官方提议中,它们被列为“可变命名的默认元组”
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>
使用数据类实现相同功能的Armor。
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)
8.隐式命名空间包(3.3+)
构建Python代码的方法之一是在软件包中(带有__init__.py文件的文件夹)。下面的示例由Python的官方文档提供。
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
…
在Python 2中,上方的每个文件夹都必须具有__init__.py文件,该文件将该文件夹转换为Python包。 在Python 3中,一旦引入了隐式命名空间包,就不再需要这些文件。
隐式命名空间包官方文档: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
…
注意:如果你认真观察的话,就会发现它并不像我在本节中所指出的那样简单,它来自正式的PEP 420规范—常规软件包仍然需要 __init__.py,将其从文件夹结构中删除会将其转变为本地名称空间带有附加限制的软件包。
9.数字文字中的下划线(3.6+)
Python3.6提供了一种很好的方法,通过在数字中启用下划线,允许读取数字文本。这可以用来演示,例如:千位、十六进制和二进制数。
cost = 10_000
print(f’Cost: {cost}’)
# Cost: 10000
hex_flag = 0xDAFE_FFF8
print(f’Hex flag: {hex_flag}’)
# Hex flag: 3674144760
binary = 0b_0011_1001
print(f’Binary: {binary}’)
# Binary: 57
Python 3.6通过使数字成为下划线来提供一种允许读取数字文字的绝佳方法。 例如,它可以用于演示:千位、十六进制和二进制数。
10.赋值表达式-“walrus运算符”(3.8+)
在Python的最新版本中,引入了walrus运算符,它能够对表达式进行变量赋值。如果你想在代码中引用表达式,并在代码中保存一两行代码,那么它会非常有用。
animals = [‘dog’, ‘lion’, ‘bear’, ‘tiger’]
for animal in animals:
if (len_animal := len(animal)) > 4:
print(f’The animal “{animal}” has “{len_animal}”, letters!’)
# The animal “tiger” has “5”, letters!
总结
可能我上面总结的内容还够不完整,如果你也了解一些我们不常用但是非常有效果的Python功能,欢迎在评论区告诉我们~ 希望以上内容能告诉你以前不知道的Python 3功能,并能让你写出更流畅,更直观的代码。