前言

如果你有掌握过其他计算机语言的话,则你学习 Python 的时候一开始将会非常容易,基本的声明,定义,基本数据类型,相关逻辑,循环,方法等,这些可以很快的掌握并适应,当然 Python 还有很多糖语法,这部分就是记录一些 Python 的小地方和一些糖语法来方便查询和学习。

前排提醒:本示例使用的 Python 版本为3.10.9

装饰器

装饰器是一种很有意思的糖语法,它可以在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能。我们来使用一个示例来理解这个装饰器的实际应用:

现在我们有一个计算两个值和的函数sum_ab,后来,我们需要改动代码,需要给这个函数增加一个打印输出提醒的功能,代码如下所示:

1
2
3
4
5
6
7
8
9
# 计算两个数的和
def sum_ab(a,b):
print(f'和为:{a+b}')


# 我们现在需要增加的功能
# 打印输出函数
def print_toast():
print('执行成功')

在常规状态下,我们可以选择将新增的功能直接编写添加到我们的sum_ab函数中,如下所示:

1
2
3
4
# 计算两个数的和
def sum_ab(a,b):
print(f'和为:{a+b}')
print_toast()

这种方法简单直接,在需要修改的代码量小的情况下可以这样做,但是对于大量的方法或者可能存在频繁修改的情况下,这种方法耗时耗力,这个时候我们可以使用一个包装器包装一下来更加简洁的实现:

1
2
3
4
5
6
7
8
def sum_ab(a,b):
print(f'和为:{a+b}')

# 我们现在需要增加的功能
# 打印输出函数
def print_toast(func):
func(1,2)
print('执行成功')

虽然,上述代码中的带参包装器有一定的逻辑问题,但是思路是正确的,我们需要通过一个包装器来在不修改原函数的情况下来实现增加额外功能,在这种需求下诞生了装饰器这种糖语法。

装饰器可以根据参数分为:有参数装饰器和无参数装饰器,两者差别不是很大。同样的装饰器还可以根据添加的额外功能位置不同分为:前置装饰器,后置装饰器和环绕装饰器

前置装饰器

现在我们来编写一个前置装饰器来实现上述说明的功能添加,代码示例:

1
2
3
4
5
6
7
8
9
10
# 前置装饰器
def print_log(func):
def wrapper(*args,**kwargs):
print("这里是添加的装饰器逻辑")
return func(*args,**kwargs)
return wrapper

@print_log # 在需要装饰的地方前面使用@+装饰器名称即可
def sum_ab(a,b):
print(f'和为:{a+b}')

运行结果:

1
2
3
4
5
sum_ab(1,2)		# 正常调用函数即可

# 输出
这是一个输出
和为:3

至于不带参数的装饰器,只需要将装饰器中的参数部分删除即可,代码示例:

1
2
3
4
5
6
# 前置装饰器
def print_log(func):
def wrapper():
print("这里是添加的装饰器逻辑")
return func()
return wrapper

后置装饰器

1
2
3
4
5
6
7
# 后置装饰器
def print_log_d(func):
def wrapper(*args,**kwargs):
result = func(*args,**kwargs)
print('这是后置装饰器')
return result
return wrapper

环绕装饰器

1
2
3
4
5
6
7
8
# 环绕装饰器
def print_log_d(func):
def wrapper(*args,**kwargs):
print('这是一个环绕装饰器')
result = func(*args,**kwargs)
print('这是后置装饰器')
return result
return wrapper

装饰器逻辑

一个方法可以嵌套多个装饰器,如下所示:

1
2
3
4
@func_1
@func_0
def func():
print('这是一个方法')

其嵌套逻辑为:func_1(func_0(func)),其他类似同理。

三元运算

对于常规的if..else运算,Python 提供了一种更加简单的方法实现,代码示例:

1
2
3
4
5
6
7
8
9
10
a = 2

# 这是常规写法
if a>1:
print('a大于1')
else:
print('a小于或者等于1')

# 这是三元运算的糖语法
print("a大于1") if a>1 else print('a小于或者等于1')

两者的运算逻辑和结果是一致的,仅仅是糖语法的写法问题。

Lambda函数

Lambda函数又称为匿名函数,是个又有趣的糖语法,在 C# 中写回调函数相关的时候经常使用会很方便。

  • 在Python中,我们使用lambda关键字来声明一个匿名函数,这就是为什么我们将它们称为“lambda函数”。匿名函数是指没有声明函数名称的函数。尽管它们在语法上看起来不同。
  • lambda 函数只能包含一个表达式,只能封装有限的逻辑

**其语法原型:name = lambda [list] : 表达式**。

现在我们直接上代码来直观的理解 Lambda 函数,代码示例:

1
2
3
4
5
6
# Lambda函数
a = lambda x,y:x+y
print(a(1,2))

# 输出
3

上述代码等同于:

1
2
3
4
5
6
7
# 常规写法
def a(x,y):
return x+y
print(a(1,2))

# 输出
3

相比函数,lambada 表达式具有以下 2 个优势:

  1. 对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁;
  2. 对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。

推导式

推导式非常好用,我在之前 Python 的基础部分的时候有写过推导式相关,这个部分继续重新说明一下,它可以很大部分情况下帮助你快速获得你想要的数据并且不需要更多的代码。列表,字典和集合中都可以使用推导式。

列表推导式

1
2
3
4
5
6
# 列表推导式
a = [x for x in range(1,10)]
print(a)

# 输出
[1, 2, 3, 4, 5, 6, 7, 8, 9]

现在我们希望输出列表中所有的偶数来组成一个新的列表,我们可以结合我们之前说明的三元运算,就可以轻松实现:

1
2
3
4
5
6
7
8
9
10
# 列表推导式
a = [x for x in range(1,10)]
print(a)
# 提取所有偶数到新的列表
b = [x for x in range(1,10) if x%2==0]
print(b)

# 输出
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 4, 6, 8]

字典推导式

1
2
3
4
5
6
7
# 字典推导式
temp_d = {'a':1,'b':2,"c":3}
temp_a = {x:y for x,y in temp_d.items() if y%2 != 0}
print(temp_a)

# 输出
{'a': 1, 'c': 3}

集合推导式

1
2
3
4
5
6
# 集合推导式
temp_x = {x**2 for x in [1, 1, 2]} #集合不允许重复
print(temp_x)

# 输出
{1, 4}

一些函数

enumerate()

该函数可以返回列表,字典或者集合等的位置索引和其值,可以更好的对列表或者其他数据结构进行处理,代码示例:

1
2
3
4
5
6
7
8
9
10
# 提取所有偶数到新的列表
b = [x for x in range(1,10) if x%2==0]
for x,y in enumerate(b):
print(x,y)

# 输出
0 2
1 4
2 6
3 8

zip()

1
2
3
4
5
6
7
8
9
10
# zip函数可以匹配多个列表
names = ['Bob','Alice','White']
ages = [22,12,18]
for name,age in zip(names,ages):
print('{0} 的年龄是:{1}'.format(name,age))

# 输出
Bob 的年龄是:22
Alice 的年龄是:12
White 的年龄是:18

参考文章