10个你没有充分利用的令人惊叹的 Python 特性
off999 2025-05-14 15:48 14 浏览 0 评论
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
相关推荐
- 让 Python 代码飙升330倍:从入门到精通的四种性能优化实践
-
花下猫语:性能优化是每个程序员的必修课,但你是否想过,除了更换算法,还有哪些“大招”?这篇文章堪称典范,它将一个普通的函数,通过四套组合拳,硬生生把性能提升了330倍!作者不仅展示了“术”,更传授...
- 7 段不到 50 行的 Python 脚本,解决 7 个真实麻烦:代码、场景与可复制
-
“本文整理自开发者AbdurRahman在Stackademic的真实记录,所有代码均经过最小化删减,确保在50行内即可运行。每段脚本都对应一个日常场景,拿来即用,无需额外依赖。一、在朋...
- Python3.14:终于摆脱了GIL的限制
-
前言Python中最遭人诟病的设计之一就是GIL。GIL(全局解释器锁)是CPython的一个互斥锁,确保任何时刻只有一个线程可以执行Python字节码,这样可以避免多个线程同时操作内部数据结...
- Python Web开发实战:3小时从零搭建个人博客
-
一、为什么选Python做Web开发?Python在Web领域的优势很突出:o开发快:Django、Flask这些框架把常用功能都封装好了,不用重复写代码,能快速把想法变成能用的产品o需求多:行业...
- 图解Python编程:从入门到精通系列教程(附全套速查表)
-
引言本系列教程展开讲解Python编程语言,Python是一门开源免费、通用型的脚本编程语言,它上手简单,功能强大,它也是互联网最热门的编程语言之一。Python生态丰富,库(模块)极其丰富,这使...
- Python 并发编程实战:从基础到实战应用
-
并发编程是提升Python程序效率的关键技能,尤其在处理多任务场景时作用显著。本文将系统介绍Python中主流的并发实现方式,帮助你根据场景选择最优方案。一、多线程编程(threading)核...
- 吴恩达亲自授课,适合初学者的Python编程课程上线
-
吴恩达教授开新课了,还是亲自授课!今天,人工智能著名学者、斯坦福大学教授吴恩达在社交平台X上发帖介绍了一门新课程——AIPythonforBeginners,旨在从头开始讲授Python...
- Python GUI 编程:tkinter 初学者入门指南——Ttk 小部件
-
在本文中,将介绍Tkinter.ttk主题小部件,是常规Tkinter小部件的升级版本。Tkinter有两种小部件:经典小部件、主题小部件。Tkinter于1991年推出了经典小部件,...
- Python turtle模块编程实践教程
-
一、模块概述与核心概念1.1turtle模块简介定义:turtle是Python标准库中的2D绘图模块,基于Logo语言的海龟绘图理念实现。核心原理:坐标系系统:原点(0,0)位于画布中心X轴:向右...
- Python 中的asyncio 编程入门示例-1
-
Python的asyncio库是用于编写并发代码的,它使用async/await语法。它为编写异步程序提供了基础,通过非阻塞调用高效处理I/O密集型操作,适用于涉及网络连接、文件I/O...
- 30天学会Python,开启编程新世界
-
在当今这个数字化无处不在的时代,Python凭借其精炼的语法架构、卓越的性能以及多元化的应用领域,稳坐编程语言排行榜的前列。无论是投身于数据分析、人工智能的探索,还是Web开发的构建,亦或是自动化办公...
- Python基础知识(IO编程)
-
1.文件读写读写文件是Python语言最常见的IO操作。通过数据盘读写文件的功能都是由操作系统提供的,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个...
- Python零基础到精通,这8个入门技巧让你少走弯路,7天速通编程!
-
Python学习就像玩积木,从最基础的块开始,一步步搭建出复杂的作品。我记得刚开始学Python时也是一头雾水,走了不少弯路。现在回头看,其实掌握几个核心概念,就能快速入门这门编程语言。来聊聊怎么用最...
- 一文带你了解Python Socket 编程
-
大家好,我是皮皮。前言Socket又称为套接字,它是所有网络通信的基础。网络通信其实就是进程间的通信,Socket主要是使用IP地址,协议,端口号来标识一个进程。端口号的范围为0~65535(用户端口...
- Python-面向对象编程入门
-
面向对象编程是一种非常流行的编程范式(programmingparadigm),所谓编程范式就是程序设计的方法论,简单的说就是程序员对程序的认知和理解以及他们编写代码的方式。类和对象面向对象编程:把...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)