写出优雅代码能提升可读性、可维护性和开发效率,减少错误,便于协作和扩展,是高质量软件开发的关键。
f-string格式化字符串
基本用法
在字符串前加上f或F,然后在字符串中用大括号包裹变量或表达式。
name = "Alice"
age = 30
print(f"My name is {name} and I am {age} years old.")
表达式
a = 5
b = 10
print(f"The sum of {a} and {b} is {a + b}.")
格式化数字
例如指定小数点后的位数、添加千位分隔符等。
pi = 3.141592653589793
print(f"Pi is approximately {pi:.2f}.") # 保留两位小数
print(f"Pi is approximately {pi:.5f}.") # 保留五位小数
格式化日期
可以与datetime模块结合,格式化日期和时间。
from datetime import datetime
now = datetime.now()
print(f"The current time is {now:%Y-%m-%d %H:%M:%S}.")
格式化字典
可以直接访问字典中的键值。
person = {"name": "Alice", "age": 30}
print(f"{person['name']} is {person['age']} years old.")
格式化对象属性
可以直接访问对象的属性。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("Alice", 30)
print(f"{person.name} is {person.age} years old.")
格式化列表和元组
直接访问列表和元组中的元素。
numbers = [1, 2, 3, 4, 5]
print(f"The first number is {numbers[0]} and the last number is {numbers[-1]}.")
格式化字符串中的占位符
f-string支持在字符串中使用占位符,占位符可以用变量名或索引。
name = "Alice"
age = 30
print(f"{name=}, {age=}.")
格式化字符串中的嵌套表达式
f-string支持嵌套表达式,可以在大括号中嵌套多个表达式。
a = 5
b = 10
print(f"The product of {a} and {b} is {(a * b):.2f}.")
格式化字符串中的循环
f-string可以与循环结合,动态生成字符串。
numbers = [1, 2, 3, 4, 5]
print(f"Numbers: {', '.join(str(n) for n in numbers)}")
格式化字符串中的多行
f-string可以用于多行字符串,通过三引号 """
或'''
定义。
name = "Alice"
age = 30
city = "New York"
print(f"""
My name is {name}.
I am {age} years old.
I live in {city}.
""")
格式化字符串中的转义
在f-string中,如果需要在字符串中包含大括号{}
,需要使用双大括号{{
和}}
来转义。
print(f"{{name}} is a placeholder for the variable name.")
交换两个变量的值
多重赋值语法,无需临时变量即可交换两个变量的值。
a, b = b, a
# 初始值
a = 1
b = 2
c = 3
print(f"交换前: a={a}, b={b}, c={c}")
# 交换值
a, b, c = b, c, a
print(f"交换后: a={a}, b={b}, c={c}")
我们的目标是将 a 的值变为 2,b 的值变为 3,c 的值变为 1。
逻辑顺序:为了实现这个目标,我们需要按照以下顺序进行赋值:
- a 应该接收 b 的值。
- b 应该接收 c 的值。
- c 应该接收 a 的值。
让字符串重复
快速生成多个相同的字符串,例如打印 5 个 "Hello",你可能会这样写:
result = "Hello " * 5
简化条件判断
# 青铜段位
num = 10
if num % 2 == 0:
result = "偶数"
else:
result = "奇数"
# 钻石段位
result = "偶数" if num % 2 == 0 else "奇数"
列表拼接成字符串
# 假设你有一组邮箱地址的列表,现在你想把它们拼接成一条 , 分隔的字符串:
emails = ["a@example.com", "b@example.com", "c@example.com"]
result = ", ".join(emails)
print(result)
字典取值
操作 Python 字典时,如果你尝试访问一个不存在的键,Python 会抛出 KeyError,但你可以使用 .get() 方法安全获取值:
data = {"name": "Alice", "age": 25}
age = data.get("age", "默认值") # 如果 'age' 存在,则返回其值,否则返回 '默认值'
print(age) # 输出 25
统计列表中元素出现的次数
擅长于用 collections 集合类。Java里边也多是用集合类操作的。
假设你有一个列表,想知道其中某个元素出现的次数,最简单的方法是使用 collections.Counter
from collections import Counter
letters = ["a", "b", "c", "a", "b", "a"]
counter = Counter(letters)
print(counter) # 输出 {'a': 3, 'b': 2, 'c': 1}
print(counter.most_common(1)) # 获取出现次数最多的元素 [('a', 3)]
列表去重
通过将列表转换为集合(set)来去除重复元素,再将集合转换回列表。set是一个无序集合,自动去除重复元素,因此这行代码可以快速实现列表去重。
lst = list(set(lst))
计算列表中数字的平均值
sum()函数计算列表中所有数字的总和,再用len()函数获取列表的长度,从而计算平均值。这种方法简洁高效。
average = sum(lst) / len(lst)
倒序排列字符串
通过[::-1]
将字符串s倒序排列。切片操作是Python中处理字符串和列表的常用技巧,简洁且高效。
reversed_str = s[::-1]
获取列表中的最大和最小值
利用max()和min()函数,分别获取列表lst中的最大值和最小值。Python的这些内建函数使得这类操作变得极其简便。
max_val, min_val = max(lst), min(lst)
判断一个数是否为质数
使用了all()函数结合列表推导式,快速判断一个数n是否为质数。它通过检查n是否能被2到sqrt(n)之间的任何数整除来判断。
is_prime = all(n % i for i in range(2, int(n**0.5) + 1))
生成一个包含1到10的数字列表
利用range()函数生成一个从1到10的数字序列,再用list()将其转换为列表。这种方法非常适合生成序列数据。
numbers = list(range(1, 11))
找出字符串中的所有数字
利用列表推导式结合isdigit()
方法,从字符串s中提取所有的数字,并将它们作为整数返回。
digits = [int(i) for i in s if i.isdigit()]
检查一个字符串是否是回文
通过字符串切片,判断字符串s是否与其倒序版本相同,从而判断是否为回文字符串。这种方法简洁且高效。
切片操作的基本语法是 s[start:stop:step],其中:
- start 是切片的起始索引(包含)。
- stop 是切片的结束索引(不包含)。
- step 是步长,表示每次取值的间隔。
is_palindrome = s == s[::-1]
获取文件的扩展名
os.path.splitext()
os.path.splitext()函数将路径分割成两部分:文件名和扩展名。
返回值是一个元组,其中第一个元素是文件名(不包括扩展名),第二个元素是扩展名。
import os
# 示例文件名
filename = "example.txt"
# 使用os.path.splitext()获取扩展名
_, ext = os.path.splitext(filename)
print(f"文件扩展名是: {ext}")
pathlib()
pathlib模块也提供了更现代的方式来处理路径。
pathlib模块中的Path对象有一个suffix属性,可以直接获取文件的扩展名。
给 enumerate() 设置起始值
我们在遍历列表时会使用 enumerate(),默认情况下,它从 0 开始计数:
# 想让索引从 1 开始,可以这样做:
for index, name in enumerate(names, start=1):
print(index, name)
合并两个字典
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
# 方法一
merged = {**dict1, **dict2}
# 方法二:Python 3.9 以后,你可以用 | 运算符更简洁地合并字典
merged = dict1 | dict2
让大数字更易读
如果你需要在代码中写入一个大数字,
比如 1000000,可能会因为数零太多而感到困惑。Python 允许你使用 下划线 _ 作为分隔符,让数字更易读:
big_number = 1_000_000 # 这个和 1000000 是一样的
print(big_number) # 输出 1000000
# 使用格式化字符串来让输出更直观:
print(f"{big_number:_}") # 输出 1_000_000
让类像函数一样调用
创建可调用的类,这样类的实例可以像函数一样使用。这是通过 __call__
方法实现的:
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, value):
return self.factor * value
double = Multiplier(2) # 创建一个倍数器
print(double(10)) # 输出 20
方法链式调用
一个类有多个方法,你需要连续调用它们。这时,我们可以返回 self,从而支持链式调用:
class Person:
def__init__(self, name, age):
self.name = name
self.age = age
defset_name(self, new_name):
self.name = new_name
returnself# 关键:返回 self 以支持链式调用
defset_age(self, new_age):
self.age = new_age
returnself# 关键:返回 self
bob = Person("Bob", 25)
bob.set_name("Alice").set_age(30) # 一行代码完成两次修改
print(bob.name, bob.age) # 输出:Alice 30
让列表输出更美观
# 有一个列表,想要以更直观的方式打印出来,你可以使用 * 运算符结合 print():
foods = ["苹果", "香蕉", "橘子"]
print(*foods, sep=", ") # 输出:苹果, 香蕉, 橘子
让对象打印更可读
如果直接打印一个对象,默认会返回类似 <__main__.Person object at 0x7ff6d8e1f9d0>
这样的信息,根本没法看懂。
我们可以定义 __repr__
方法,让它返回更有意义的字符串:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name={self.name}, age={self.age})"
bob = Person("Bob", 25)
print(bob) # 输出:Person(name=Bob, age=25)
一行代码获取列表的首尾元素
假设你有一个列表 people = ["Bob", "Alice", "Charlie", "David"]
,想要获取第一个和最后一个元素,你可以这样做:
# *middle 会捕获中间所有的元素,而 first 和 last 则分别获取开头和结尾的元素。
first, *middle, last = people
print(first, last) # 输出:Bob David
数字四舍五入
# 保留小数位数
print(round(3.14159, 2)) # 输出:3.14
# -2 表示保留到百位,类似于“银行家舍入法”,让数据更加易读。
print(round(12345, -2)) # 输出:12300
按自定义规则找出最值
Python 内置的 max() 和 min() 支持自定义规则。
# 例如,找出字母 a 出现最多的名字
names = ["Timothy", "Bob", "James", "Zebra", "Amanda", "Anna", "Luigi"]
most_a_name = max(names, key=lambda x: x.lower().count("a"))
print(most_a_name) # 输出:Amanda
# 还可以按字符串长度查找最短和最长的名字:
shortest_name = min(names, key=len)
longest_name = max(names, key=len)
print(shortest_name, longest_name) # 输出:Bob Timothy
解包操作:优雅地处理序列
解包(unpacking)是一个非常强大的特性。它让我们能够用一行代码就完成多个变量的赋值操作。
# 基础解包
x, y = 1, 2
# x=1, y=2
# 交换变量值(无需临时变量)
a, b = b, a
# 解包列表/元组
first, *rest = [1, 2, 3, 4, 5] # first=1, rest=[2,3,4,5]
*begin, last = [1, 2, 3, 4, 5] # begin=[1,2,3,4], last=5
# 忽略某些值
name, _, age = ['Alice', 'Smith', 25] # 忽略中间值
上下文管理器
使用上下文管理器可以确保资源使用更加安全可靠。
# 自定义一个简单的上下文管理器
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
self.end = time.time()
print(f"代码块执行时间:{self.end - self.start}秒")
with Timer():
# 模拟耗时操作
time.sleep(1)
*args
和**kwargs
*args
用于接收任意数量的位置参数(非关键字参数)。这些参数会被收集到一个元组中。 语法:在函数定义中,*args
放在参数列表的最后,用于接收所有未被其他参数捕获的位置参数。 用途:当你不确定函数会接收多少个位置参数时,可以使用 *args
。
def print_args(*args):
for arg in args:
print(arg)
print_args(1, 2, 3, "hello", [1, 2, 3])
###### 输出 ######
# 1
# 2
# 3
# hello
# [1, 2, 3]
**kwargs
用于接收任意数量的关键字参数。这些参数会被收集到一个字典中。 语法:在函数定义中,**kwargs
放在参数列表的最后,用于接收所有未被其他参数捕获的关键字参数。 用途:当你不确定函数会接收多少个关键字参数时,可以使用 **kwargs
。
def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_kwargs(name="小明", age=18, city="北京")
###### 输出 ######
# 位置参数: (1, 2, 3)
# 关键字参数: {'name': '小明', 'age': 18}
顺序:*args
必须放在 **kwargs
之前。 解包:你可以在调用函数时使用 *
和 **
来解包元组和字典,将它们作为参数传递。
args = (1, 2, 3)
kwargs = {"name": "小明", "age": 18}
print_info(*args, **kwargs)
赋值表达式
海象运算符(:=)
是Python 3.8引入的一个新特性,也被称为“赋值表达式”(assignment expression)。
它允许你在表达式中进行赋值操作,这在条件判断中特别有用,可以减少代码的重复和提高可读性。
# 不使用海象运算符
text = "Hello, Python!"
length = len(text)
if length > 10:
print(f"文本长度为{length},超过10个字符")
# 使用海象运算符
if (length := len(text)) > 10:
print(f"文本长度为{length},超过10个字符")
all 和 any
all(iterable):检查可迭代对象中的所有元素是否都为真。如果所有元素都为真,则返回 True;否则返回 False。
result = all([True, 1, 'non-empty string']) # 返回 True
检查可迭代对象中是否存在至少一个为真的元素。如果存在至少一个为真的元素,则返回 True;否则返回 False。
result = any([False, 0, None, 'exists']) # 返回 True
结合生成器表达式优化性能
在处理大型数据集时,直接使用列表作为参数可能会导致性能问题,因为所有元素需要先被存入内存。
all 和 any 支持生成器表达式,可以以惰性评估的方式逐步计算,从而大幅提升性能。
# 文件行检查
def all_lines_match(file_path, condition):
with open(file_path, 'r') as file:
return all(condition(line) for line in file)
# 示例条件:行长度必须大于10
result = all_lines_match('large_file.txt', lambda line: len(line) > 10)
print(result) # 如果所有行都满足条件,返回 True
与自定义类结合,实现灵活逻辑
# 权限验证系统
class User:
def __init__(self, permissions):
self.permissions = permissions
def has_permission(self, permission):
return permission in self.permissions
def can_user_execute(user, required_permissions):
return all(user.has_permission(perm) for perm in required_permissions)
# 示例用法
user = User(['read', 'write', 'delete'])
permissions_needed = ['read', 'write']
print(can_user_execute(user, permissions_needed)) # True
结合逻辑表达式实现动态决策
# 智能筛选系统
def filter_products(products, filters):
return [
product for product in products
if all(condition(product) for condition in filters)
]
# 示例数据
products = [
{'name': 'Laptop', 'price': 1000, 'stock': 10},
{'name': 'Smartphone', 'price': 500, 'stock': 0},
{'name': 'Tablet', 'price': 300, 'stock': 5},
]
# 筛选条件
filters = [
lambda p: p['price'] < 800, # 价格小于800
lambda p: p['stock'] > 0 # 有库存
]
result = filter_products(products, filters)
print(result) # [{'name': 'Tablet', 'price': 300, 'stock': 5}]
短路逻辑,避免不必要的计算
all 和 any 都具备短路逻辑特性。当 all 遇到 False 或 any 遇到 True 时,会立即停止后续的评估。
# 深度数据校验
data = {'user': {'profile': {'age': 30}}}
def is_valid(data):
return all([
'user' in data,
'profile' in data.get('user', {}),
data['user']['profile'].get('age') > 18
])
print(is_valid(data)) # True
动态生成复杂条件
# 动态表单验证
def validate_form(data, rules):
return all(rule(data.get(field, None)) for field, rule in rules.items())
# 示例规则
rules = {
'username': lambda x: isinstance(x, str) and len(x) > 3,
'age': lambda x: isinstance(x, int) and x > 18,
'email': lambda x: '@' in x if isinstance(x, str) else False
}
form_data = {'username': 'Alice', 'age': 25, 'email': 'alice@example.com'}
print(validate_form(form_data, rules)) # True
On this page
- f-string格式化字符串
- 基本用法
- 表达式
- 格式化数字
- 格式化日期
- 格式化字典
- 格式化对象属性
- 格式化列表和元组
- 格式化字符串中的占位符
- 格式化字符串中的嵌套表达式
- 格式化字符串中的循环
- 格式化字符串中的多行
- 格式化字符串中的转义
- 交换两个变量的值
- 让字符串重复
- 简化条件判断
- 列表拼接成字符串
- 字典取值
- 统计列表中元素出现的次数
- 列表去重
- 计算列表中数字的平均值
- 倒序排列字符串
- 获取列表中的最大和最小值
- 判断一个数是否为质数
- 生成一个包含1到10的数字列表
- 找出字符串中的所有数字
- 检查一个字符串是否是回文
- 获取文件的扩展名
- os.path.splitext()
- pathlib()
- 给 enumerate() 设置起始值
- 合并两个字典
- 让大数字更易读
- 让类像函数一样调用
- 方法链式调用
- 让列表输出更美观
- 让对象打印更可读
- 一行代码获取列表的首尾元素
- 数字四舍五入
- 按自定义规则找出最值
- 解包操作:优雅地处理序列
- 上下文管理器
- *args和**kwargs
- *args
- **kwargs
- 赋值表达式
- all 和 any
- 结合生成器表达式优化性能
- 与自定义类结合,实现灵活逻辑
- 结合逻辑表达式实现动态决策
- 短路逻辑,避免不必要的计算
- 动态生成复杂条件