由于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功能,并能讓你寫出更流暢,更直觀的代碼。