
大家好,我是你们的新朋友 AI云溪。
生成一个九九乘法表是很多 Pythoner 学习编程的起点。如下标准的嵌套循环的代码:
for i in range(1, 10):for j in range(1, i+1): print(f"{j}×{i}={i*j:2d}", end=" ") print()如果我们想用最优方案输出一个九九乘法表呢?大家可能容易想到用嵌套列表推导式:
print("\n".join(" ".join(f"{j}×{i}={i*j:2d}"for j in range(1, i+1)) for i in range(1, 10)))这样代码只有一行,看起来更简洁了,但不够优雅。还有没有别的方法?我们可以用 NumPy 提供的乘法功能:
import numpy as npx = np.arange(1,10)print(np.multiply.outer(x,x))我们在选择用何种代码实现功能时,需要根据实际情况进行权衡,尽量保持 Python 的语言风格简洁、明晰、优雅。
Simple is better than complex. Errors should never pass silently. —— Zen of Python
今天我们就来盘点一下那些使代码变得更 Pythonic 的语法糖(Syntactic Sugar)。
import numpy as np # 模块别名from datetime import datetime as dt # 成员别名a += b # 等价于 a = a + ba -= b # a = a - ba *= b # a = a * ba /= b # a = a / ba //= b # a = a // ba %= b # a = a % ba **= b # a = a ** ba &= b # a = a & b (位与)a |= b # a = a | b (位或)a ^= b # a = a ^ b (位异或)a <<= b # a = a << b (左移)a >>= b # a = a >> b (右移)# 语法糖 result = "成年人"if age >= 18else"未成年人"# 等价于if age >= 18: result = "成年人"else: result = "未成年人"列表推导式(List Comprehension)可以用一行代码代替多行 for 循环,是 Python 最具特色的语法之一。本文开篇已经举了用列表推导式生成九九乘法表的例子。我们再来看看它在数据预处理方面的强大功能:
# 清洗字符串列表raw_data = [' apple ', 'banana', ' cherry ', ' pitaya']cleaned = [item.strip() for item in raw_data] # 去除空格print(cleaned) # ['apple', 'banana', 'cherry', 'pitaya']# 转换数据类型str_numbers = ['2', '4', '6', '8', '10']int_numbers = [int(n) for n in str_numbers] #字符串转整型print(int_numbers) # [2, 4, 6, 8, 10]# 处理缺失值PCP_data = [26.5, None, 0, None, 17.2, 8.6]cleaned_data = [x if x isnotNoneelse-999for x in PCP_data] #缺失值设为-999print(cleaned_data) # [26.5, -999, 0, -999, 17.2, 8.6]f-string 可以称得上是最便捷的格式化字符串表达方式了,它允许我们在字符串中直接嵌入表达式或变量。
设置字符串对齐格式:
name = "slowbirdearlystarts"print(f"左对齐: {name:<10} |") # 左对齐,占10位print(f"居中对齐: {name:^10} |") # 居中对齐,占10位print(f"右对齐: {name:>10} |") # 右对齐,占10位设置有效数字:
pi = 3.1415926535print(f'圆周率:{pi:.3f}') # 保留三位小数嵌入日期变量:
from datetime import datetimenow = datetime.now()print(f"今天是:{now:%Y年%m月%d日,%A}")Python 中,@是装饰器的语法糖,它的作用是省略了“手动将函数传入装饰器并重新赋值”的步骤,让代码更简洁。@property是一个专门用于类中的装饰器。它的作用是将类中的方法变为属性访问,从而让你可以像访问属性一样访问方法,而不需要再显式调用。
property 机制有什么用?假设我们有一个类 Student , 他有一个属性 score。你可能会这样写:
classStudent:def_init_(self,score): self.score = score现在,如果学生成绩 score 的总分是100,有人把它设为 120,这显然是不合理的,那我们能不能在设置 score 时做一些检查呢?
在构造函数的时候,其实我们可以添加一些验证和限制条件,以防不合理的域外值输入:
classStudent:def_init_(self,score):if age < 0:raise ValueError('score must be smaller than or equal to 100') self.score = score但是问题来了,构造函数只会在对象初始化的时候会被调用,后续并不会验证报错。引入 property 机制可以解决这个问题。我们可以将 score 属性定义为 property, 执行自定义的验证逻辑。
classStudent:def_init_(self,score): self.set_score(score)defget_score(self):return self._scoredefset_score(self,score):if score > 100:raise ValueError('math_score must be smaller than or equal to 100') self._score = score score = property(get_score,set_score) # 注意顺序不能乱第一个必须写get上面的代码中我们将 score 属性使用 property 函数来定义,然后将 get_score 和 set_score 作为参数传入,那么 score 每次被赋值的时候都会调用 set_score 方法来做必要的检查,以防止域外值的输入。
with 语句的核心作用是自动处理资源的获取与释放,它确保没有资源意外打开。with 语句在文件操作、数据库连接、网络连接等方面用途强大。我们这里举一个最简单的例子来理解 with 的作用。 一般情况,我们用以下方法读写文件:
f = open("test.txt","w")f.write("Halo World")f.close()但是,上述代码如果在调用 write() 的过程中出现了异常,则 close() 方法无法被执行,因此资源就会一直占用无法被释放。
当然,我们可以用 try/finally 来防止因异常而占用资源:
try: f = open("test.txt","w") f.write("Halo World")except ValueError as error: print(error)finally: f.close()但 Python 提供了一种管理资源的更简单方法:上下文管理器。with语句的语法糖代码:
with open("test.txt","w") as file: file.write("Halo World")labmda 函数借鉴了数学计算模型中的 λ演算 , 其核心思想是将变量、函数定义、函数应用在一行内完成。lambda函数的语法表示为:lambda <参数>: <表达式>
在上述用列表推导式实现的数据清洗的功能,我们也完全可以用lambda表达式配合高阶函数map( )实现同样的功能,代码改写如下:
# 数据清洗raw_data = [' apple ', 'banana', ' cherry ', ' pitaya']cleaned = list(map(lambda x: x.strip() if x.strip() elseNone, raw_data))print(cleaned) # 类型转换data = ['2', '4', '6', '8', '10']converted = list(map(lambda x: int(x), data))print(converted) # 处理缺失值PCP_data = [26.5, None, 0, None, 17.2, 8.6]transformed = list(map(lambda x: x if x isnotNoneelse-999, PCP_data))print(transformed) enumerate函数是一个迭代器,会产生包含两个元素的元组 (index, value),其中 index 是元素的索引, value 是元素的值。
numbers = [2,4,6,8,10]# 找出所有2的整数幂power2_items = list(filter(lambda x: x[1]&(x[1]-1)==0,enumerate(numbers)))print(power2_items)输出: [(0, 2), (1, 4), (3, 8)]海象运算符 (:=)是 Python 3.8 引入的一个新特性,它允许我们在表达式中直接进行变量赋值,而无需单独使用 = 语句。例如给学生考试成绩添加限制条件的这段代码:
score = input("请输入学生成绩:")if score > 100: print("无效成绩!")用海象运算符可以写成:
if (score := input("请输入学生成绩:")) and score > 100: print("无效成绩!")以上10个语法糖尽显 Python 的强大与优雅,熟练掌握就能显著提升你的编码效率和代码质量。但是,语法糖虽好,可不要贪吃哦。有时候过度使用语法糖也会让代码变得难以理解,提高了团队成员协作的成本;并且,炼丹小白在初期更不必过分追求代码的语法糖写法,还是应该打好基础。如何掌控代码简洁、明晰、优雅之间微妙的平衡,需要我们在实践经验的积累中精进。