12、Python 之函数:你的代码是一整坨还是分块的

目录

引言

函数的好处

函数的基本用法

参数默认值的用法

lambda函数(匿名函数)

总结


引言

在前面的文章中,已经提过,所谓编程,核心内容只有两块:数据的表示、数据的处理。数据的表示可以通过各种基本类型、容器类型的组合来实现;数据的处理,就是在顺序、循环、分支的框架下,对数据结构进行不断重新赋值。

刚开始学习编程的新手,似乎不太习惯使用用户自定义函数(User Defined Function, UDF)来编写数据的处理功能。习惯于在脚本中按顺序进行语句与表达式的堆砌。

如果数据处理的逻辑表简单的话,不使用函数也是可以的,毕竟够用就好。但是,如果数据处理的逻辑比较复杂的话,还是使用代码一行行堆积来实现功能,就不太合适了……

可以想象一下,要从一坨几百行、几千行、甚至更多行的代码中读懂处理逻辑,然后还要进行修改、扩充。单单只是读,可能都要吐了。

程序员最怕的有两件事:1)读别人的代码;2)读自己的代码。

所以,为了避免日后自己看吐或者把别人看吐,UDF还是需要学一下的。

函数的好处

Python程序员首先应该考虑的代码整理工具就是函数(function)。与其他编程语言一样,Python的函数也可以把大段程序分解为多个小块儿,并且用直观的名字表示每块儿代码的用途。这样可以让代码更好理解,也更容易复用与重构。

简单梳理一下,在编程中,使用函数的好处有如下:

  • 代码的复用:一次定义,多次调用。
  • 提高代码的可维护性:代码复用的情况下,一次修改,多处生效。
  • 逻辑分离与模块化:代码不再是一整坨,而是一块块的。
  • 提高代码的可读性:代码逻辑分离与模块化之后,自然更加易读、易于维护。
  • 提高可扩展性:使用函数,可以更加容易进行功能的添加、或者修改。
  • 易于调试:模块化的好处,可以各自独立进行功能的调试,快速定位到问题。

函数的基本用法

编程语言中的函数概念,可以类比于数学中的函数的概念。函数的用途在于对数据进行处理,所以,通常需要有输入数据、数据处理逻辑、和输出数据。

在Python中自定义一个函数,可以如下操作:

def my_sum(a, b):
    """
        计算两个数的和,并返回
    :param a:
    :param b:
    :return: a + b
    """
    return a + b

可以大概看到一个函数的构成,主要包含:

  • def关键字:用于定义函数。
  • 函数头:函数名(参数列表),参数列表可以为空。
  • docstring:函数的说明文档,以三个引号括起来的字符串,可以没有,如果有,需要放在行数体内的第一行。
  • 函数体:数据的处理逻辑代码。
  • 返回值:使用return语句将要输出的数据进行返回,可以没有,没有的话,就是返回None。

以上只是一个函数的定义,要把函数的功能用起来,需要对函数进行调用:

result = my_sum(10, 20)
print(result)

调用函数非常简单,只需要将参数对应传入即可。
通过赋值语句接收函数的返回值。

参数默认值的用法

Python支持在函数的定义过程中,给部分参数设置默认值,从而支持当默认情况满足需求的情况下,减少参数个数的传递,从而更加便于使用。而且,可以通过参数默认值,增加函数的灵活性。
比如:登录用户,能够获取到用户名,如果未登录用户,则以‘游客’来称呼:

def greet(username='游客'):
    return f"{username},您好,欢迎使用XXX系统"


print(greet())
print(greet('南宫理'))

执行结果:

需要注意的是,带默认值的参数,只能出现在参数列表的最后,可以是多个,否则会报语法错误。

这个语法规定,应该很好理解,如果你是Python解释器,你怎么处理带默认值的参数,才能不会出现二义性呢。

lambda函数(匿名函数)

本着能用一行代码解决的事情,绝不写第二行的理念。有些情况下,使用def定义函数,有点繁琐了……

好在Python提供了lambda函数的支持。

lambda函数一种匿名函数,可以实现在一行代码中定义一个功能相对简单的函数。直接上代码:

my_sum = lambda a, b: a + b
result = my_sum(10, 20)
print(result)

greet = lambda username='游客': f'{username},您好,欢迎使用XXX系统'
print(greet())
print(greet('南宫理'))

前面两个简单函数的lambda实现,确实少了一行代码。
但是,其实lambda函数,更多地应用于将函数作为参数传递的场景,比如,当我们使用内置函数sorted()时,先看下sorted()函数的说明文档:

函数中有个key参数,用于传递一个表示排序规则的函数,函数返回一个新的list,包含排序之后的数据,而不会修改原来的对象。
此外,sorted函数还有一个带默认值的参数reverse=False,表示默认按照升序排列。

以一个关于成绩排序的场景,来简单使用一下该函数:

from faker import Faker
# 从rich模块导入print,覆盖builtins中的print
from rich import print
from rich.console import Console
console = Console()

fk = Faker('zh_CN')
# 生成测试数据,姓名,语文成绩、数学成绩、英语成绩
scores = [{'name': fk.name(), 'chinese': fk.random_int(0, 100), 'math': fk.random_int(0, 100),
           'english': fk.random_int(0, 100)} for i in range(5)]


def get_chinese(score):
    return score['chinese']


scores_sort_by_chinese = sorted(scores, key=get_chinese)
console.rule('排序前')
print(scores)
console.rule('排序后')
print(scores_sort_by_chinese)

执行结果:

这里,定义了一个get_chinese()的函数,作为key的参数。由于排序的规则比较简单,更适合使用lambda函数。

from faker import Faker
# 从rich模块导入print,覆盖builtins中的print
from rich import print
from rich.console import Console
console = Console()

fk = Faker('zh_CN')
# 生成测试数据,姓名,语文成绩、数学成绩、英语成绩
scores = [{'name': fk.name(), 'chinese': fk.random_int(0, 100), 'math': fk.random_int(0, 100),
           'english': fk.random_int(0, 100)} for i in range(5)]

scores_sort_by_chinese = sorted(scores, key=lambda score: score['chinese'])
scores_sort_by_math = sorted(scores, key=lambda score: score['math'], reverse=True)
scores_sort_by_english = sorted(scores, key=lambda score: score['english'], reverse=True)
console.rule('排序前')
print(scores)
console.rule('按语文成绩升序排序')
print(scores_sort_by_chinese)
console.rule('按数学成绩降序排序')
print(scores_sort_by_math)
console.rule('按英语成绩降序排序')
print(scores_sort_by_english)

执行结果:

总结

由于篇幅所限,这篇文章只介绍了关于函数的优点,以及函数的一些基础用法。最后在介绍lambda函数的时候,以一个简单的实际案例做了演示。案例中用到的rich和faker第三方框架,在前面的文章中已经介绍过,为了便于不熟悉的小伙伴学习使用,省去到故纸堆里搜检的工作,我把链接附在文章末尾。

3、Python之Faker:更巧妙的批量数据生成

5、Python之rich:GUI之外,终端呈现也能玩出花

  • 37
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫理的日知录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值