网站首页 > 技术文章 正文
Python 的简单性和多功能性使其成为全球开发人员的最爱。每天有超过 1000 万开发者使用 Python 进行从网络开发、机器学习到网络脚本等各种开发,Python 的功能非常强大。然而,我们中的许多人可能并没有充分利用这些功能。在这篇博客中,我将介绍一些你可能没有充分利用的神奇 Python 功能。
1.Pathlib
-- 将杂乱无章的文件路径转化为流畅的面向对象操作
Python 中的 pathlib 模块提供了一种面向对象的方法来处理文件系统路径。与 os.path 等传统方法相比,它提供了一种更直观、更易读的方法来处理文件路径。
有了 pathlib,路径被视为对象,从而可以更轻松地执行连接路径、检查文件是否存在、读/写文件等操作。
from pathlib import Path
# Create a Path object
path = Path('/path/to/directory')
# Access parts of the path
print(path.name) # 'directory'
print(path.parent) # '/path/to'
print(path.suffix) # ''
# Join paths
path = Path('/path/to')
new_path = path / 'directory' / 'file.txt'
# Checking if path exits
if path.exists():
print("The file exists")
else:
print("The file does not exist")
# Reading from a file
path = Path('/path/to/file.txt')
content = path.read_text()
print(content)
# Listing Directory Contents
for file in path.iterdir():
print(file)
官方文档:
https://docs.python.org/3/library/pathlib.html
2. Dataclass
-- 让 Python 来处理繁重的工作,而你则专注于数据
在 Python 3.7 中引入的 Python 数据类模块提供了一个装饰器 (@dataclass),它能为类自动生成特殊方法,如 __init__(), __repr__(), __eq__() 等。它通过减少模板代码,简化了主要用于存储数据的类的创建。
数据类减少了对以数据为中心的类中模板代码的需求,使开发人员能够专注于逻辑而不是编写多余的代码。它能自动处理初始化实例、比较对象和打印类的可读表示等常见任务。此外,数据类还支持默认值、类型提示和不变性,只需极少的工作量。
from dataclasses import dataclass
@dataclass
class Product:
name: str
price: float
quantity: int = 0
category: str = "General"
# Method to restock the product
def restock(self, amount: int) -> None:
self.quantity += amount
print(f"Restocked {amount} units of {self.name}. Total now: {self.quantity}")
# Method to sell the product
def sell(self, amount: int) -> None:
if self.quantity >= amount:
self.quantity -= amount
print(f"Sold {amount} units of {self.name}. Remaining: {self.quantity}")
else:
print(f"Not enough stock to sell {amount} units. Only {self.quantity} available.")
# Method to display product info
def display_info(self) -> None:
print(f"Product: {self.name}")
print(f"Category: {self.category}")
print(f"Price: ${self.price}")
print(f"Stock: {self.quantity} units")
# Example usage
product = Product(name="Laptop", price=999.99, quantity=5, category="Electronics")
# Restocking the product
product.restock(10)
# Selling the product
product.sell(3)
# Displaying product information
product.display_info()
3.海象操作符(Walrus)
walrus 操作符 (:=) 是 Python 3.8 中引入的赋值表达式。它允许你为表达式中的变量赋值。在引入之前,赋值只允许在独立语句中进行,但 walrus 操作符允许在循环、条件和函数调用等表达式中进行赋值。
海象操作符将赋值和求值合并为一个步骤,从而减少了冗余,这在循环和条件语句中尤其有用。它提高了可读性和效率,无需单独的赋值步骤,从而减少了代码行数。此外,当需要评估和赋值一个将被多次使用的值时,它还有助于简化代码。
while True:
user_input = input("Enter a valid string (non-empty): ")
if len(user_input) > 0:
break
print(f"Valid input received: {user_input}")
在上述代码中,字符串被评估了两次,一次是在读取输入时,另一次是在 if 条件中检查其长度。
我们看看改用海象操作符的效果:
while (user_input := input("Enter a valid string (non-empty): ")) and len(user_input) == 0:
print("Invalid input, try again.")
print(f"Valid input received: {user_input}")
这段代码的关键部分是 user_input := input(...),其中的 := 就是“海象操作符”。它的作用是同时赋值和返回值。这意味着 user_input := input(...) 这个表达式会把 input() 的结果赋给 user_input,同时这个表达式的返回值也是 input() 的结果。所以,在 while 循环条件中,不仅仅是检查 user_input,而且还会在检查的同时给 user_input 赋值。
换句话说,这里我们通过海象操作符让代码可以在一行里完成输入和赋值,并立即对输入进行检查。
4. Getter & Setters
-- 代码的无声保护者,巧妙地保护着数据。
Getters 和 setters 是用于获取(检索)和设置(修改)类中私有属性值的方法。它们控制对对象内部状态的访问,执行规则和验证,同时保持实际数据的封装。
在 Python 中,@property 装饰器创建了一种 Pythonic 方法来实现Getters 和 Setters,而无需像普通方法那样调用它们。
- 它确保只能设置有效值,避免不必要的错误。
- 它允许你在不影响外部代码的情况下更改内部实现。
我们看下面这个例子,我希望创建一个余额永远不会为负的 BankAccount 类:
class BankAccount:
def __init__(self, balance):
self.balance = balance
account = BankAccount(100)
account.balance = -50 ## Negative Input
使用上述方法可能会导致出现负的账户余额,从而破坏代码和逻辑,而使用 setters 可以确保余额始终为非负,从而提供安全性和验证。
class BankAccount:
def __init__(self, balance):
self._balance = None # private attribute
self.balance = balance # invoke setter
@property
def balance(self):
return self._balance
@balance.setter
def balance(self, value):
if value < 0:
raise ValueError("Balance cannot be negative!")
self._balance = value
# Usage
account = BankAccount(100)
print(account.balance) # 100
account.balance = -50 # Raises ValueError: Balance cannot be negative!
经常使用 Getter 和 Setter 非常重要,因为让用户随意修改你的数据,就像让小孩开车一样危险!
5. Memory Slots
在 Python 中,__slots__ 特性通过限制对象的属性来减少内存的使用。通常,Python 使用动态字典 (__dict__)来存储对象的属性,这样做有一定的灵活性,但会消耗更多的内存。
想象一下,在一个每个用户只需要几个属性(姓名、电子邮件)的系统中,你要创建数百万个轻量级用户对象。减少内存使用量可以大大提高性能。
class User:
def __init__(self, name, email):
self.name = name
self.email = email
# Creating a million users without `__slots__`
users = [User(f"User{i}", f"@example.com">user{i}@example.com") for i in range(1000000)]
在上述情况下,Python 为每个 User 对象分配一个内部字典(__dict__),用来存储对象的属性(即 name 和 email)。由于字典的灵活性,用户可以动态添加新的属性,比如 user1.age = 25。这种灵活性使得每个对象都维护一个独立的字典,而字典结构会占用额外的内存空间。因此当需要创建 100 万个对象时,每个对象都有自己的字典,整体内存占用会较大。对于内存敏感的应用,这可能成为一个问题。
为了解决这个问题,我们可以这样改写代码:
class User:
__slots__ = ['name', 'email'] # Declare fixed attributes
def __init__(self, name, email):
self.name = name
self.email = email
# Creating a million users with `__slots__`
users = [User(f"User{i}", f"@example.com">user{i}@example.com") for i in range(1000000)]
在优化后的版本中,__slots__ 明确指定了类的属性为 name 和 email,这样 Python 不会为每个对象创建 __dict__,而是直接为每个对象分配固定的内存块来存储这些属性。这种方式省去了字典开销,内存占用显著减少。这在需要创建大量对象时可以节省大量内存。
6. functools.lru_cache
在 Python 中,functools.lru_cache 是一个装饰器,它为函数添加了一种简单但有效的缓存机制。缓存(Memoization)是一种通过存储耗时函数调用的结果,并在相同输入再次出现时返回缓存结果的技术,用于加速程序执行。
对于计算量大或经常调用相同参数的函数,这可以大大提高性能。
from functools import lru_cache
@lru_cache(maxsize=None) # maxsize=None means the cache can grow indefinitely
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
# Calculate Fibonacci numbers
print(fibonacci(10)) # Output: 55
print(fibonacci(15)) # Output: 610
示例解释:
- @lru_cache(maxsize=None) 修饰了 fibonacci 函数,使缓存大小不受限制(maxsize=None)。
- fibonacci 函数以递归方式计算斐波那契数字,但通过将结果存储在缓存中避免了冗余计算。
如果不进行内存化,递归计算斐波那契数的效率会因重复计算而降低。使用 lru_cache 进行记忆化可以存储之前计算的结果,减少冗余计算,显著提高性能。
7. Callable
在 Python 中,__call__ 是一种特殊的方法,它允许类的实例像函数一样运行。在类中定义 __call__ 时,可以像函数一样调用对象本身,传递参数并接收返回值。它为对象的交互和行为方式增加了灵活性。
假设你正在为一个 API 创建一个速率限制器,需要限制函数被调用的频率。
class RateLimiter:
def __init__(self, limit):
self.limit = limit
def is_allowed(self, requests):
return requests <= self.limit
limiter = RateLimiter(100)
print(limiter.is_allowed(80)) # True
没有 __call__ 时,每次都需要明确调用 is_allowed,但有了 __call__ 后,RateLimiter 实例的行为就像一个函数,使代码更简单、更整洁。
class RateLimiter:
def __init__(self, limit):
self.limit = limit
def __call__(self, requests):
return requests <= self.limit
# Now you can call the object like a function
limiter = RateLimiter(100)
print(limiter(80)) # True
print(limiter(120)) # False
8. Generators & Yield
Generators 是 Python 中一种特殊的函数类型,使用 yield 关键字返回迭代器。Generators 不会一次性返回所有结果,而是每次生成一个值,允许你按需惰性地迭代数据。这意味着它只在需要时计算值,从而节省内存和处理时间,特别是在处理大型数据集时。
假设你正在处理一个庞大的日志文件,读取每一行并筛选特定的关键字。Generators 可以在不将整个文件载入内存的情况下处理每一行。
def process_logs(filename):
logs = []
with open(filename) as file:
for line in file:
if "ERROR" in line:
logs.append(line)
return logs
# This will load all lines into memory
logs = process_logs("server.log")
for log in logs:
print(log)
这种方法会将整个日志文件加载到内存中,对于大文件来说并不理想。可以使用Generators改写:
def process_logs(filename):
with open(filename) as file:
for line in file:
if "ERROR" in line:
yield line
# Using a generator to process logs lazily
for log in process_logs("server.log"):
print(log)
9. Suppress
Suppress 是一个 Python 上下文管理器,你可以使用它选择性地忽略某些错误,而不是用多个 try-except 块来封装您的代码。如果你知道某些异常是可以忽略的,那么它就能提供更简洁、更易读的代码。
举个例子,在进行文件操作时,文件可能不存在,但这对程序并不重要。与其抛出错误或明确捕获错误,不如简单地抑制错误并继续前进。
使用try-except:
try:
os.remove("non_existent_file.txt")
except FileNotFoundError:
pass
改用Suppress:
from contextlib import suppress
import os
# Suppress the FileNotFoundError if the file doesn't exist
with suppress(FileNotFoundError):
os.remove("non_existent_file.txt")
Suppress上下文管理器可以优雅地处理异常,而不需要显式异常处理,从而使代码更加简洁。
10.MappingProxy
MappingProxyType 是 Python 字典的不可变封装。它允许对字典进行只读访问,同时防止修改原始数据。这在需要保护数据但又希望数据可读时特别有用。
假设你正在管理一个系统的配置字典。多个组件都需要读取配置,但任何人都不能在配置设置后对其进行修改。如果使用普通字典:
config = {"debug": True, "version": "1.0"}
# Anyone can modify the configuration
config["version"] = "2.0"
在这种情况下,任何可以访问配置字典的人都可以更改它。而 MappingProxyType 可以将配置字典封装为只读版本,确保任何人都无法在创建后更改它。
from types import MappingProxyType
config = {"debug": True, "version": "1.0"}
# Create a read-only view of the dictionary
read_only_config = MappingProxyType(config)
# Attempt to modify will raise a TypeError
try:
read_only_config["version"] = "2.0"
except TypeError:
print("Cannot modify a read-only dictionary.")
# You can still access values
print(read_only_config["version"]) # 1.0
猜你喜欢
- 2025-05-21 Python 之 logging 模块详解
- 2025-05-21 避坑!Python任意参数黑科技:一招搞定参数洪水!90%都不知道
- 2025-05-21 Python常用文件操作库使用详解
- 2025-05-21 2025-05-16:字符至少出现 K 次的子字符串Ⅰ。用go语言,给定一个
- 2025-05-21 Python的装饰器还是不会?来看看这篇文章(建议收藏)
- 2025-05-21 必知必会的15个Python知识点
- 2025-05-21 Linux离线安装Python3教程
- 2025-05-21 你可能不知道的实用 Python 功能
- 05-25Python 3.14 t-string 要来了,它与 f-string 有何不同?
- 05-25Python基础元素语法总结
- 05-25Python中的变量是什么东西?
- 05-25新手常见的python报错及解决方案
- 05-2511-Python变量
- 05-2510个每个人都是需要知道Python问题
- 05-25Python编程:轻松掌握函数定义、类型及其参数传递方式
- 05-25Python基础语法
- 257℃Python短文,Python中的嵌套条件语句(六)
- 257℃python笔记:for循环嵌套。end=""的作用,图形打印
- 256℃PythonNet:实现Python与.Net代码相互调用!
- 251℃Python操作Sqlserver数据库(多库同时异步执行:增删改查)
- 251℃Python实现字符串小写转大写并写入文件
- 106℃原来2025是完美的平方年,一起探索六种平方的算吧
- 91℃Python 和 JavaScript 终于联姻了!PythonMonkey 要火?
- 81℃Ollama v0.4.5-v0.4.7 更新集合:Ollama Python 库改进、新模型支持
- 最近发表
- 标签列表
-
- python中类 (31)
- python 迭代 (34)
- python 小写 (35)
- python怎么输出 (33)
- python 日志 (35)
- python语音 (31)
- python 工程师 (34)
- python3 安装 (31)
- python音乐 (31)
- 安卓 python (32)
- python 小游戏 (32)
- python 安卓 (31)
- python聚类 (34)
- python向量 (31)
- python大全 (31)
- python次方 (33)
- python桌面 (32)
- python总结 (34)
- python浏览器 (32)
- python 请求 (32)
- python 前端 (32)
- python验证码 (33)
- python 题目 (32)
- python 文件写 (33)
- python中的用法 (32)