最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

幾個(gè)有趣的Python庫(kù),建議收藏~

2023-07-10 15:18 作者:一起學(xué)chatGPT一起學(xué)ai  | 我要投稿


隨著每個(gè) Python 版本的發(fā)布,都會(huì)添加新模塊,并引入新的更好的做事方式,雖然我們都習(xí)慣了使用好的舊 Python 庫(kù)和某些做事方式,但現(xiàn)在也時(shí)候升級(jí)并利用新的和改進(jìn)的模塊及其特性了。

Pathlib

pathlib 絕對(duì)是 Python 標(biāo)準(zhǔn)庫(kù)中最近添加的更大的內(nèi)容之一, 自 Python 3.4 以來(lái),它一直是標(biāo)準(zhǔn)庫(kù)的一部分,但很多人仍然使用 os 模塊進(jìn)行文件系統(tǒng)操作。

然而,pathlib 與舊的 os.path 相比具有許多優(yōu)點(diǎn) - 雖然 os 模塊以原始字符串格式表示路徑,但 pathlib 使用面向?qū)ο蟮臉邮?,這使得它更具可讀性和編寫(xiě)自然:

from pathlib import Path
import os.path

# 老方式
two_dirs_up = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 新方式,可讀性強(qiáng)
two_dirs_up = Path(__file__).resolve().parent.parent

路徑被視為對(duì)象而不是字符串這一事實(shí)也使得可以創(chuàng)建一次對(duì)象,然后查找其屬性或?qū)ζ溥M(jìn)行操作:

readme = Path("README.md").resolve()

print(f"Absolute path: {readme.absolute()}")
# Absolute path: /home/martin/some/path/README.md
print(f"File name: {readme.name}")
# File name: README.md
print(f"Path root: {readme.root}")
# Path root: /
print(f"Parent directory: {readme.parent}")
# Parent directory: /home/martin/some/path
print(f"File extension: {readme.suffix}")
# File extension: .md
print(f"Is it absolute: {readme.is_absolute()}")
# Is it absolute: True

我最喜歡 pathlib 的一個(gè)特性是可以使用 /(“除法”)運(yùn)算符來(lái)連接路徑:

# Operators:
etc = Path('/etc')

joined = etc / "cron.d" / "anacron"
print(f"Exists? - {joined.exists()}")
# Exists? - True

重要的是要注意 pathlib 只是替代 os.path 而不是整個(gè) os 模塊, 它還包括 glob 模塊的功能,因此如果你習(xí)慣于將 os.path 與 glob.glob 結(jié)合使用,那么你可以完全用pathlib替代它們。

在上面的片段中,我們展示了一些方便的路徑操作和對(duì)象屬性,但 pathlib 還包括你習(xí)慣于 os.path 的所有方法,例如:

print(f"Working directory: {Path.cwd()}") # same as os.getcwd()
# Working directory: /home/martin/some/path
Path.mkdir(Path.cwd() / "new_dir", exist_ok=True) # same as os.makedirs()
print(Path("README.md").resolve()) # same as os.path.abspath()
# /home/martin/some/path/README.md
print(Path.home()) # same as os.path.expanduser()
# /home/martin

有關(guān) os.path 函數(shù)到 pathlib 中新函數(shù)的完整映射,請(qǐng)參閱 官方文檔。

Secrets

說(shuō)到 os 模塊,你應(yīng)該停止使用的另一部分是 os.urandom。相反,你應(yīng)該使用自 Python 3.6 以來(lái)可用的新秘密模塊:

# 老方式:
import os

length = 64

value = os.urandom(length)
print(f"Bytes: {value}")
# Bytes: b'\xfa\xf3...\xf2\x1b\xf5\xb6'
print(f"Hex: {value.hex()}")
# Hex: faf3cc656370e31a938e7...33d9b023c3c24f1bf5

# 新方式:
import secrets

value = secrets.token_bytes(length)
print(f"Bytes: {value}")
# Bytes: b'U\xe9n\x87...\x85>\x04j:\xb0'
value = secrets.token_hex(length)
print(f"Hex: {value}")
# Hex: fb5dd85e7d73f7a08b8e3...4fd9f95beb08d77391

使用 os.urandom 實(shí)際上并不是這里的問(wèn)題,引入secrets模塊的原因是因?yàn)槿藗兪褂秒S機(jī)模塊來(lái)生成密碼等,即使隨機(jī)模塊不產(chǎn)生密碼安全令牌。

根據(jù)文檔,隨機(jī)模塊不應(yīng)用于安全目的, 你應(yīng)該使用 secrets 或 os.urandom,但 secrets 模塊絕對(duì)更可取,因?yàn)樗容^新,并且包含一些用于十六進(jìn)制令牌的實(shí)用程序/便利方法以及 URL 安全令牌。

Zoneinfo

在 Python 3.9 之前,沒(méi)有用于時(shí)區(qū)操作的內(nèi)置庫(kù),所以每個(gè)人都在使用 pytz,但現(xiàn)在我們?cè)跇?biāo)準(zhǔn)庫(kù)中有 zoneinfo,所以是時(shí)候切換了。

from datetime import datetime
import pytz # pip install pytz

dt = datetime(2022, 6, 4)
nyc = pytz.timezone("America/New_York")

localized = nyc.localize(dt)
print(f"Datetime: {localized}, Timezone: {localized.tzname()}, TZ Info: {localized.tzinfo}")

# 新方式:
from zoneinfo import ZoneInfo

nyc = ZoneInfo("America/New_York")
localized = datetime(2022, 6, 4, tzinfo=nyc)
print(f"Datetime: {localized}, Timezone: {localized.tzname()}, TZ Info: {localized.tzinfo}")
# Datetime: 2022-06-04 00:00:00-04:00, Timezone: EDT, TZ Info: America/New_York

datetime 模塊將所有時(shí)區(qū)操作委托給抽象基類(lèi) datetime.tzinfo, 這個(gè)抽象基類(lèi)需要一個(gè)具體的實(shí)現(xiàn)——在引入這個(gè)很可能來(lái)自 pytz 的模塊之前?,F(xiàn)在我們?cè)跇?biāo)準(zhǔn)庫(kù)中有 zoneinfo,我們可以使用它。

然而,使用 zoneinfo 有一個(gè)警告——它假定系統(tǒng)上有可用的時(shí)區(qū)數(shù)據(jù),UNIX 系統(tǒng)就是這種情況, 如果你的系統(tǒng)沒(méi)有時(shí)區(qū)數(shù)據(jù),那么你應(yīng)該使用 tzdata 包,它是由 CPython 核心開(kāi)發(fā)人員維護(hù)的第一方庫(kù),其中包含 IANA 時(shí)區(qū)數(shù)據(jù)庫(kù)。

Dataclasses

Python 3.7 的一個(gè)重要補(bǔ)充是 dataclasses 包,它是 namedtuple 的替代品。

你可能想知道為什么需要替換 namedtuple?以下是你應(yīng)該考慮切換到數(shù)據(jù)類(lèi)的一些原因:

  • 它可以是可變的

  • 默認(rèn)提供 repr、eqinit、hash 魔術(shù)方法,

  • 允許指定默認(rèn)值,

  • 支持繼承。

    此外,數(shù)據(jù)類(lèi)還支持 frozenslots(從 3.10 開(kāi)始)屬性以提供與命名元組的特征奇偶校驗(yàn)。

切換真的不應(yīng)該太難,因?yàn)槟阒恍枰亩x:

# 老方式:
# from collections import namedtuple
from typing import NamedTuple
import sys

User = NamedTuple("User", [("name", str), ("surname", str), ("password", bytes)])

u = User("John", "Doe", b'tfeL+uD...\xd2')
print(f"Size: {sys.getsizeof(u)}")
# Size: 64

# 新方式:
from dataclasses import dataclass

@dataclass()
class User:
name: str
surname: str
password: bytes

u = User("John", "Doe", b'tfeL+uD...\xd2')

print(u)
# User(name='John', surname='Doe', password=b'tfeL+uD...\xd2')

print(f"Size: {sys.getsizeof(u)}, {sys.getsizeof(u) + sys.getsizeof(vars(u))}")
# Size: 48, 152

在上面的代碼中,我們還包含了大小比較,因?yàn)檫@是 namedtuple 和數(shù)據(jù)類(lèi)之間的較大差異之一,如上所見(jiàn),命名元組的大小要小得多,這是由于數(shù)據(jù)類(lèi)使用 dict 來(lái)表示屬性。

至于速度比較,除非你計(jì)劃創(chuàng)建數(shù)百萬(wàn)個(gè)實(shí)例,否則屬性的訪問(wèn)時(shí)間應(yīng)該基本相同,或者不夠重要:

import timeit

setup = '''
from typing import NamedTuple
User = NamedTuple("User", [("name", str), ("surname", str), ("password", bytes)])
u = User("John", "Doe", b'')
'''


print(f"Access speed: {min(timeit.repeat('u.name', setup=setup, number=10000000))}")
# Access speed: 0.16838401100540068

setup = '''
from dataclasses import dataclass

@dataclass(slots=True)
class User:
name: str
surname: str
password: bytes

u = User("John", "Doe", b'')
'''


print(f"Access speed: {min(timeit.repeat('u.name', setup=setup, number=10000000))}")
# Access speed: 0.17728697300481144

如果以上內(nèi)容說(shuō)服了你打算切換到數(shù)據(jù)類(lèi),請(qǐng)盡快嘗試吧

相反,如果你不想切換并且出于某種原因真的想使用命名元組,那么你至少應(yīng)該使用鍵入模塊而不是collections中的 NamedTuple:

# 不好方式的:
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])

# 更好的方式:
from typing import NamedTuple
class Point(NamedTuple):
x: float
y: float

最后,如果你既不使用 namedtuple 也不使用數(shù)據(jù)類(lèi),你可能需要考慮直接使用 Pydantic。

Proper Logging

這不是標(biāo)準(zhǔn)庫(kù)的最新添加,但值得使用 - 你應(yīng)該使用正確的日志記錄而不是打印語(yǔ)句, 如果你在本地調(diào)試問(wèn)題,則可以使用 print,但對(duì)于任何無(wú)需用戶(hù)干預(yù)即可運(yùn)行的生產(chǎn)就緒程序,正確的日志記錄是必須的。

特別是考慮到設(shè)置 Python 日志記錄非常簡(jiǎn)單:

import logging
logging.basicConfig(
filename='application.log',
level=logging.WARNING,
format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
datefmt='%H:%M:%S'
)

logging.error("Some serious error occurred.")
# [12:52:35] {<stdin>:1} ERROR - Some serious error occurred.
logging.warning('Some warning.')
# [12:52:35] {<stdin>:1} WARNING - Some warning.

與打印語(yǔ)句相比,上面的簡(jiǎn)單配置將為你提供卓越的調(diào)試體驗(yàn), 最重要的是,你可以進(jìn)一步自定義日志庫(kù)以記錄到不同的位置、更改日志級(jí)別、自動(dòng)輪換日志等。

f-strings

Python 包含很多格式化字符串的方法,包括 C 樣式格式化、f 字符串、模板字符串或 .format 函數(shù), 不過(guò),其中之一 - f-strings - 格式化的字符串文字 , 它們寫(xiě)起來(lái)更自然,可讀性更強(qiáng),并且是前面提到的選項(xiàng)中最快的。

因此,我認(rèn)為沒(méi)有必要爭(zhēng)論或解釋為什么要使用它們,然而,在某些情況下不能使用 f 字符串:

使用 % 格式的唯一原因是用于記錄:

import logging

things = "something happened..."

logger = logging.getLogger(__name__)
logger.error("Message: %s", things) # 評(píng)估內(nèi)部記錄器方法
logger.error(f"Message: {things}") # 立即評(píng)估

在上面的示例中,如果你使用 f 字符串,則表達(dá)式將立即計(jì)算,而使用 C 樣式格式,替換將被推遲到實(shí)際需要時(shí),這對(duì)于消息分組很重要,其中具有相同模板的所有消息都可以記錄為一個(gè), 這不適用于 f 字符串,因?yàn)槟0逶趥鬟f給記錄器之前填充了數(shù)據(jù)。

此外,有些事情是 f-strings 根本無(wú)法做到的, 例如在運(yùn)行時(shí)填充模板 - 即動(dòng)態(tài)格式 - 這就是 f-strings 被稱(chēng)為文字字符串格式的原因:

# 動(dòng)態(tài)設(shè)置模板及其參數(shù)
def func(tpl: str, param1: str, param2: str) -> str:
return tpl.format(param=param1, param2=param2)

some_template = "First template: {param1}, {param2}"
another_template = "Other template: {param1} and {param2}"

print(func(some_template, "Hello", "World"))
print(func(another_template, "Hello", "Python"))

# 動(dòng)態(tài)重用具有不同參數(shù)的相同模板.
inputs = ["Hello", "World", "!"]
template = "Here's some dynamic value: {value}"

for value in inputs:
print(template.format(value=value))

最重要的是,盡可能使用 f 字符串,因?yàn)樗鼈兏呖勺x性和更高性能,但請(qǐng)注意,在某些情況下仍然首選和/或需要其他格式樣式。

Tomllib

TOML 是一種廣泛使用的配置格式,對(duì)于 Python 的工具和生態(tài)系統(tǒng)尤其重要,因?yàn)樗糜?pyproject.toml 配置文件, 到目前為止,你必須使用外部庫(kù)來(lái)管理 TOML 文件,但是從 Python 3.11 開(kāi)始,將有一個(gè)名為 tomllib 的內(nèi)置庫(kù),它基于 toml 包。

所以,一旦你切換到 Python 3.11,你應(yīng)該養(yǎng)成使用 import tomllib 而不是 import tomli 的習(xí)慣。少了一種需要擔(dān)心的依賴(lài)!

# import tomli as tomllib
import tomllib

with open("pyproject.toml", "rb") as f:
config = tomllib.load(f)
print(config)
# {'project': {'authors': [{'email': 'contact@martinheinz.dev',
# 'name': 'Martin Heinz'}],
# 'dependencies': ['flask', 'requests'],
# 'description': 'Example Package',
# 'name': 'some-app',
# 'version': '0.1.0'}}

toml_string = """
[project]
name = "another-app"
description = "Example Package"
version = "0.1.1"
"""


config = tomllib.loads(toml_string)
print(config)
# {'project': {'name': 'another-app', 'description': 'Example Package', 'version': '0.1.1'}}

Setuptools

最后一個(gè)更像是棄用通知:

由于 Distutils 已棄用,因此同樣不鼓勵(lì)使用任何來(lái)自 distutils 的函數(shù)或?qū)ο?,Setuptools 旨在替換或棄用所有此類(lèi)用途。

是時(shí)候告別 distutils 包并切換到 setuptools 了,setuptools 文檔提供了有關(guān)如何替換 distutils 用法的指導(dǎo), 除此之外,PEP 632 還為 setuptools 未涵蓋的部分 distutils 提供遷移建議。

總結(jié)

每個(gè)新的 Python 版本都會(huì)帶來(lái)新的特性,因此我建議你查看 Python 發(fā)行說(shuō)明中的“新模塊”、“不推薦使用的模塊”和“已刪除的模塊”部分,這是了解 Python 標(biāo)準(zhǔn)重大變化的好方法 , 通過(guò)這種方式,你可以不斷地將新功能和最佳實(shí)踐整合到你的項(xiàng)目中。





幾個(gè)有趣的Python庫(kù),建議收藏~的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
历史| 吉水县| 永顺县| 龙口市| 威海市| 渑池县| 万载县| 靖州| 西昌市| 屏山县| 文昌市| 确山县| 宝清县| 曲周县| 尼玛县| 绍兴县| 天津市| 定结县| 株洲市| 同江市| 平乡县| 黄平县| 长乐市| 南投县| 阳东县| 东宁县| 厦门市| 商水县| 彩票| 神池县| 南雄市| 临漳县| 荆门市| 于田县| 桐乡市| 开江县| 嘉义县| 宝鸡市| 芮城县| 娱乐| 舟曲县|