一、函数作用

代码出现大量重复操作时,考虑将操作重构为函数(Functions)。

例如,我们想做一个记账本,记录日期、地点和消费内容及金额。

不用函数时,我们要这样写:

print("5月10号")print("去水果店")print("买苹果,花费5.2元")print("5月11号")print("去水果店")print("买橘子,花费6元")print("5月12号")print("去超市")print("买牛奶,花费60元")

看起来很多重复的地方,我们把核心内容抽象出来,然后封装成函数。

记录日期、地点和消费内容及金额,这些内容会改变,我们把它们作为参数传递给函数((date, place, item, price)作为参数传入函数)。

def record_consume(date, place, item, price):    print(date)    print(f"去{place}")    print(f"买{item},花费{price}元")record_consume("5月10日", "水果店", "苹果", 5.2)record_consume("5月11日", "水果店", "橘子", 6)record_consume("5月12日", "超市", "牛奶", 60)

定义函数后,我们只需要用函数名(参数)方式调用

(record_consume("5月10日", "水果店", "苹果", 5.2))。

二、函数定义

2.1 函数的定义和调用

def record_consume(date, place, item, price):    """记账函数,传入参数日期,地点,物品,价格"""    print(date)    print(f"去{place}")    print(f"买{item},花费{price}元")record_consume("5月10日", "水果店", "苹果", 5.2)

可以看出函数定义的语法:

定义 函数使用关键字 def,后跟函数名与括号内的形参列表。函数语句从下一行开始,并且有4空格缩进。

def 函数名(参数列表):    函数内容

函数内的第一条语句是字符串时,该字符串就是文档字符串,也称为 docstring,利用文档字符串可以自动生成文档,还可以让开发者在浏览代码时直接查阅文档;最好养成在代码中加入文档字符串的好习惯。


函数执行的过程:

有实际值的实参 传递给 函数中形式上占位的参数(形参


具体细节:(初次阅读时可跳过)

函数在 执行 时使用函数局部变量符号表,所有函数变量赋值都存在局部符号表中。

引用变量的查找顺序从从内到外的。首先,在局部符号表里查找变量,然后,是外层函数局部符号表,再是全局符号表,最后是内置名称符号表。因此,尽管可以引用全局变量和外层函数的变量,但最好不要在函数内直接赋值(除非是 global 语句定义的全局变量,或 nonlocal 语句定义的外层函数变量)。

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用 按值调用 来传递的(该 是对象的 引用 而不是对象的值)。1当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。


上面我们定义了一个没有返回值的函数,

下面来看一个有返回值的函数,该函数使用return 返回一个列表。

def distance_to_avg(scores):    """计算到平均值的差值"""    avg = sum(scores) / len(scores)    return [x - avg for x in scores]scores = [90, 80, 70, 80, 90]distances = distance_to_avg(scores) # 将返回的列表赋值给distances变量print(distances)

2.2 函数参数

2.2.1 默认值参数

如果参数中某些值通常固定,可以为它设置默认值。

语法:

def 函数名(必选参数,默认值参数=默认值):

例如:我们有一个计算列表均值或总和的函数,我们通常使用均值功能,因此将mood设置默认值为‘avg’。

def calculate_list_sta(list_a, mood='avg'):    if mood == 'avg':        return sum(list_a) / len(list_a)    elif mood == 'sum':        return sum(list_a)    else:        return -1

调用时默认模式就是'avg',只有模式不是'avg'的时候需要传mood参数。

scores = [90, 80, 70, 80, 90]avg = calculate_list_sta(scores)s = calculate_list_sta(scores,"sum")print(avg,s)

关于默认值的细节:

默认值在定义作用域里的函数定义中求值:

i = 5def f(arg=i):    print(arg)i = 6f()  # 5

默认值只计算一次,使用列表、字典等可变对象时,会产生累积效果。

def f(a, L=[]):    L.append(a)    return Lprint(f(1)) #[1]print(f(2)) #[1, 2]print(f(3)) #[1, 2, 3]

调用f(2)的时候,L不再赋值为[],而是使用已有的L=[1]。

如果不想在后续调用之间共享默认值,应该使用下面方法:

def f(a, L=None):    if L is None:        L = []    L.append(a)    return L

默认值为None,在函数内赋值[]。

2.2.2 关键字参数

可用key=value 形式关键字参数调用函数。

例如:

print(calculate_list_sta(scores, 'sum'))print(calculate_list_sta(list_a=scores, mood='sum'))print(calculate_list_sta(mood='sum', list_a=scores))print(calculate_list_sta(mood='sum',scores)) # 错误,位置参数必须在关键字参数前

2.2.3 *name 和 **name形式参数

*name 接收一个元组,该元组包含形参列表之外的参数。

**name接收一个字典。

def cheeseshop(kind, *arguments, **keywords):    print("-- Do you have any", kind, "?")    print("-- I'm sorry, we're all out of", kind)    for arg in arguments:        print(arg)    print("-" * 40)    for kw in keywords:        print(kw, ":", keywords[kw])
cheeseshop("Limburger", "It's very runny, sir.",           "It's really very, VERY runny, sir.",           shopkeeper="Michael Palin",           client="John Cleese",           sketch="Cheese Shop Sketch")

"Limburger"传给kind,剩下的被传给*arguments,下面三行的key=value形式被当成字典,传给**keywords。

-- Do you have any Limburger ?-- I'm sorry, we're all out of LimburgerIt's very runny, sir.It's really very, VERY runny, sir.----------------------------------------shopkeeper : Michael Palinclient : John Cleesesketch : Cheese Shop Sketch

2.2.4 特殊参数

通常,参数传递有上面的两种方式,位置参数,关键字参数。

通过/和*标记,可以限制传参方式。

/前面仅限位置参数,

*后面仅限关键字参数

def standard_arg(arg):    print(arg)standard_arg(2)standard_arg(arg=2)def pos_only_arg(arg, /):    print(arg)pos_only_arg(1)pos_only_arg(arg=1)    #报错,只能通过位置传参,不能用关键字传参def kwd_only_arg(*, arg):    print(arg)kwd_only_arg(3)     #报错,只能关键字传参kwd_only_arg(arg=3)# /前面仅位置传参,*后面仅关键字,standard不受约束def combined_example(pos_only, /, standard, *, kwd_only):    print(pos_only, standard, kwd_only)combined_example(1, 2, kwd_only=3)  combined_example(1, standard=2, kwd_only=3)

限制传参方式可以避免潜在的传参冲突问题:

def foo(name, **kwds):    return 'name' in kwdsfoo(1, **{'name': 2}) # 冲突,1会先传递给name,{'name':2}会以关键字方式再传递给name

使用位置限定就可以避免,现在name只能从通过位置参数传递。

def foo(name, /, **kwds):    return 'name' in kwdsprint(foo(1, **{'name': 2}))

2.2.5 任意实参列表

*arg可以传递可变数量的实参。

def write_multiple_items(file, separator, *args):    file.write(separator.join(args))

通常,可变参数*arg放在最后。因为它会把剩余的参数全部读入。*arg后面的只能是关键字参数。

def concat(*args, sep="/"):    return sep.join(args)concat("earth", "mars", "venus")concat("earth", "mars", "venus", sep=".")

2.3 解包实参列表

使用*解包(unpack),将参数从列表中取出:

list(range(3, 6))            # 正常调用,使用两个参数args = [3, 6]list(range(*args))            # 使用解包(unpack),两个参数从列表中取出

同样,字典可以用 ** 操作符传递关键字参数:

def parrot(voltage, state='a stiff', action='voom'):    print("-- This parrot wouldn't", action, end=' ')    print("if you put", voltage, "volts through it.", end=' ')    print("E's", state, "!")d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}parrot(**d)

2.4 Lambda 表达式

lambda 关键字用于创建小巧的匿名函数。例如:lambda a, b: a+b 函数返回两个参数的和。在语法上,它只能是单个表达式。在语义上,它只是常规函数的语法糖。

最常见的用法是用在排序中,将其作为排序的关键字函数。

pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]pairs.sort(key=lambda pair: pair[1])pairs

三、提升函数可读性

3.1 文档字符串

文档字符串用来说明对象用途。

第一行为摘要。大写字母开头,句号结尾。

第二行空白。

后面可以包含若干段落,描述对象的使用等。

def my_function():    """Do nothing, but document it.    No, really, it doesn't do anything.    """    passprint(my_function.__doc__)
#输出:Do nothing, but document it.    No, really, it doesn't do anything.

3.2 函数注解

注解(annotations)用来说明数据类型。以字典形式存放在函数的__annotations__属性中,不会影响函数的其他部分。

语法:形参后跟:标注参数类型,参数列表后用 -> 返回值类型。

def 函数名(形参: 参数类型, 关键字参数: 参数类型 = '默认值') -> 返回值类型:
def f(ham: str, eggs: str = 'eggs') -> str:    print("Annotations:", f.__annotations__)    print("Arguments:", ham, eggs)    return ham + ' and ' + eggs

3.3 编码风格

当代码变长、变复杂时,统一、可读性高的编码风格非常重要。

PEP 8 (Python Enhancement Proposal,python增强建议)是Python风格指南。内容比较多,可以去官网查看:https://peps.python.org/pep-0008/ 后面我也会整理一部分常用的。

另外补充一个技巧,如果你用的是PyCharm,可以通过Reformat(快捷键:ctrl+alt+enter)进行格式化代码,优化代码排版。



本文思维导图:


点击下方,关注公众号一只大鸽子,零基础入门Python。

Python零基础入门-4 使用函数减少重复操作相关推荐

  1. 〖Python零基础入门篇㉛〗- 函数的定义与使用

    订阅 Python全栈白宝书-零基础入门篇 可报销!白嫖入口-请点击我.推荐他人订阅,可获取扣除平台费用后的35%收益,文末名片加V! 说明:该文属于 Python全栈白宝书专栏,免费阶段订阅数量43 ...

  2. 【学习记录】Python零基础入门(五)

    第五章 Python零基础入门之条件.循环及其他语句 本人自学的主要教材为Magnus Lie Hetland的Beginning Python:From Novice to Professional ...

  3. python零基础入门教程视频下载-Python零基础入门学习视频教程全42集,资源教程下载...

    课程名称 Python零基础入门学习视频教程全42集,资源教程下载 课程目录 001我和Python的第一次亲密接触 002用Python设计第一个游戏 003小插曲之变量和字符串 004改进我们的小 ...

  4. python基础教程视频教程百度云-Python零基础入门学习视频教程全42集百度云网盘下载...

    课程简介 Python零基础入门学习视频教程全42集百度云网盘下载 课程目录 042魔法方法:算术运算 041魔法方法:构造和析构 040类和对象:一些相关的BIF 039类和对象拾遗 038类和对象 ...

  5. 11岁过python1级_11岁表弟写的Python零基础入门笔记!

    一.Python输入与输出输出:使用print()函数. print()函数的基本语法格式如下:print(输出内容). 输出内容可以是数字和字符串(字符串需要用引号括起来),也可以是包含运算符的表达 ...

  6. python基础代码大全-python零基础入门命令方式汇总大全,快速恶补你的Python基础...

    原标题:python零基础入门命令方式汇总大全,快速恶补你的Python基础 无意中浏览到这篇来自大牛的分享,总结的很全面,我重新排版下放在这里,希望能帮助到大家.在此十分感谢原作者! 在开始之前还是 ...

  7. 视频教程-Python零基础入门教程-Python

    Python零基础入门教程 从2012年从事互联网至今有7年软件编程经验,曾任职国内北京互联网公司,中南林业大学授课Python 现任逻辑教育Python课程负责人,精通Python语言,精通人工智能 ...

  8. python零基础入门教程(非常详细),从零基础入门到精通,看完这一篇就够了

    前言 本文罗列了了python零基础入门到精通的详细教程,内容均以知识目录的形式展开. 第一章:python基础之markdown Typora软件下载 Typora基本使用 Typora补充说明 编 ...

  9. python基础教程百度云-Python零基础入门学习视频教程全42集百度云网盘下载

    课程简介 Python零基础入门学习视频教程全42集百度云网盘下载 课程目录 042魔法方法:算术运算 041魔法方法:构造和析构 040类和对象:一些相关的BIF 039类和对象拾遗 038类和对象 ...

最新文章

  1. php脚本函数,PHP执行系统命令函数实例讲解
  2. [引]ASP.NET 中 事务处理(SqlTransaction)示例
  3. CSS3 Animation动画的十二原则
  4. hdu1025 Constructing Roads In JGShining#39;s Kingdom(二分+dp)
  5. 超级干货:你应该知道的那些编程原则!!
  6. 【Gans入门】Pytorch实现Gans代码详解【70+代码】
  7. 仿VS窗体效果+outlookbar效果
  8. 【NOI2016】国王饮水记【贪心】【斜率优化】【决策单调性】
  9. android8修改默认壁纸,给surfaceview设置默认背景
  10. 实现图片的变亮,变暗,灰白
  11. Apache Sqoop性能调整
  12. 入选互联网名人堂的三位中国人
  13. 深度学习-深度卷积神经网络发展
  14. 左外连接Left-Outer-Join的基于SQL,MapReduce,sparkRDD,sparkDataFrame以及spark SQL的实现案例及对比
  15. 一个苏州IT人的5年挨踢经历-------面试,薪资,企业,经历全方位揭示(之二)
  16. 像“Casa Amor”一样做营销
  17. -Xms -Xmx等jvm参数的含义
  18. 买服务器做网站 镜像选什么,如何做网站镜像,网站镜像方法
  19. python小工具-批量压缩图片
  20. lol更新后连接不上服务器未响应,LOL登录错误服务器未响应 更新后无法进入游戏解决方法推荐...

热门文章

  1. Speedoffice(excel)如何快捷隐藏表格内所有空行
  2. 常用的UML建模详解
  3. Unity 使用BitmapFont制作自定义字体
  4. 力扣(700.701)补9.9
  5. 我如何从月薪8K到25K?现在分享给大家自己的经历
  6. mac使用my-mind思维导图
  7. 【python学习】自定义三维向量类 加减乘除查看值和长度
  8. 新手小白进阶_枚举 enum
  9. html打开方式怎么没有反应,为什么我点开启程序没反应
  10. 手游无限多开器安卓版_手游多开器安卓版-手游多开器手机版 _5577安卓网