Python 核心技术与实战
景霄
Facebook 资深工程师
114324 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 47 讲
开篇词 (1讲)
Python 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

09 | 不可或缺的自定义函数

闭包
嵌套函数
默认值
参数类型
示例
外部函数返回函数
nonlocal关键字
global关键字
全局变量
局部变量
示例
返回值
参数
def语句
总结
闭包
函数变量作用域
函数基础
思考题
Python函数的概念及应用

该思维导图由 AI 生成,仅供参考

你好,我是景霄。
实际工作生活中,我曾见到不少初学者编写的 Python 程序,他们长达几百行的代码中,却没有一个函数,通通按顺序堆到一块儿,不仅让人读起来费时费力,往往也是错误连连。
一个规范的值得借鉴的 Python 程序,除非代码量很少(比如 10 行、20 行以下),基本都应该由多个函数组成,这样的代码才更加模块化、规范化。
函数是 Python 程序中不可或缺的一部分。事实上,在前面的学习中,我们已经用到了很多 Python 的内置函数,比如 sorted() 表示对一个集合序列排序,len() 表示返回一个集合序列的长度大小等等。这节课,我们主要来学习 Python 的自定义函数。

函数基础

那么,到底什么是函数,如何在 Python 程序中定义函数呢?
说白了,函数就是为了实现某一功能的代码段,只要写好以后,就可以重复利用。我们先来看下面一个简单的例子:
def my_func(message):
print('Got a message: {}'.format(message))
# 调用函数 my_func()
my_func('Hello World')
# 输出
Got a message: Hello World
其中:
def 是函数的声明;
my_func 是函数的名称;
括号里面的 message 则是函数的参数;
而 print 那行则是函数的主体部分,可以执行相应的语句;
在函数最后,你可以返回调用结果(return 或 yield),也可以不返回。
总结一下,大概是下面的这种形式:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Python中的自定义函数是编写模块化、规范化代码的不可或缺的一部分。本文介绍了函数的基础知识,包括函数的定义、参数传递、返回值等。通过示例演示了如何定义和调用函数,以及函数的嵌套和参数默认值的使用。文章还强调了Python的动态类型和多态特性,以及函数嵌套对内部数据的隐私保护和程序运行效率的提升作用。总之,自定义函数在Python编程中具有重要意义,能够提高代码的可读性和可维护性,同时也展现了Python语言的灵活性和便利性。 此外,文章还介绍了Python函数中变量的作用域,包括局部变量和全局变量的定义和使用,以及在函数内部改变全局变量值的方法。另外,闭包的概念也得到了详细解释,强调了闭包的简洁性和可读性,以及与嵌套函数相比的优势。 总的来说,本文通过深入浅出的方式,全面介绍了Python函数的概念及其应用,包括参数类型、默认值、作用域、嵌套函数和闭包等内容。读者可以从中了解到Python函数的灵活性和强大功能,以及如何利用这些特性编写高效、可维护的代码。文章还提出了思考题,鼓励读者分享自己在实际工作中遇到的嵌套函数或闭包的例子,促进交流和学习。 总体而言,本文内容丰富、深入浅出,适合Python初学者和有一定基础的开发者阅读,能够帮助他们更好地理解和应用Python函数的相关知识。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Python 核心技术与实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(78)

  • 最新
  • 精选
  • William
    快排封装,增加index参数会用到嵌套。 ```python def quickSort(arr): def partition(arr, left, right): pivot = arr[left] while left < right: while left < right and arr[right] > pivot: right -= 1 if left < right: arr[left] = arr[right] while left < right and arr[left] < pivot: left += 1 if left < right: arr[right] = arr[left] arr[left] = pivot return left def innerQuickSort(arr, left, right): stack = [] stack.append(left) stack.append(right) while len(stack) > 0: right = stack.pop() left = stack.pop() pivotIndex = partition(arr, left, right) if pivotIndex + 1 < right: stack.append(pivotIndex+1) stack.append(right) if left + 1 < pivotIndex: stack.append(left) stack.append(pivotIndex - 1) innerQuickSort(arr, 0, len(arr)-1) arr = [394, 129, 11, 39, 28] quickSort(arr) print(arr) ```

    作者回复: 嗯嗯,学习很细心

    2019-05-29
    10
  • Geek_7777
    闭包,调用square(2),这个参数2为啥能传给base,不太懂请教下

    作者回复: 因为这里square=nth_power(2)已经是一个函数了,这个函数有两个参数,已经接受了exponent,因此如果你调用了square(2),这个参数会再传给base,这样就能输出结果了

    2020-02-16
    3
    6
  • Vincent
    关于嵌套函数:“我们只能通过调用外部函数 connect_DB() 来访问它,这样一来,程序的安全性便有了很大的提高。” 这个怎么就安全了呢?这个安全指的是什么安全呢?

    作者回复: 数据库的用户名密码等一些信息不会暴露在外部的API中

    2019-05-29
    6
  • Gfcn
    没想到连闭包都讲,真的是干货满满,32个赞

    作者回复: 谢谢支持

    2019-09-30
    5
  • 路伴友行
    顺便我想多问一句,在Python里是不推荐使用递归的,是因为Python没有对递归做优化,那使用 yield from 来代替递归会不会好些呢? 其实我上一个例子就是一个尝试,我之前只尝试过打印栈信息,只看到有2层,就是不清楚有些其他什么弊端。

    作者回复: 你说的没错

    2019-05-29
    5
  • JOKERBAI
    老师,您说的“函数的调用和声明哪个在前哪个在后是无所谓的。”请问这句话怎么理解呢? 如下是会报异常NameError: name 'f' is not defined: f() def f(): print("test")

    作者回复: 文中已经更新了。可能之前表达的不准确,意思是主程序调用函数时,必须保证这个函数此前已经定义过,但是,如果我们在函数内部调用其他函数,函数间哪个声明在前、哪个在后就无所谓,因为def是可执行语句,函数调用前都不存在,我们只需保证调用时,所需的函数都已经声明定义

    2019-05-29
    4
    5
  • SCAR
    老师函数嵌套的作用二的例子,如果是在大量的调用函数时,可能还是分开检查和递归比较好,因为嵌套内函数是函数的一个local变量,在大量调用函数的时候,local变量是不断产生和销毁的,这会非常费时间,它可能会反噬掉一次类型检查节省下来的时间。看下面我贴出的计算1百万次100阶乘的时间,所以还是要根据具体情况来定,当然大部分时候函数不会这么大量调用。 def factorial(input): # validation check if not isinstance(input, int): raise Exception('input must be an integer.') if input < 0: raise Exception('input must be greater or equal to 0' ) ... def inner_factorial(input): if input <= 1: return 1 return input * inner_factorial(input-1) return inner_factorial(input) def factorial_1(input): # validation check if not isinstance(input, int): raise Exception('input must be an integer.') if input < 0: raise Exception('input must be greater or equal to 0' ) def inner_factorial_1(input): if input <= 1: return 1 return input*inner_factorial_1(input-1) %%time for i in range(1000000): factorial(100) CPU times: user 21.6 s, sys: 11.6 ms, total: 21.6 s Wall time: 21.7 s %%time for i in range(1000000): factorial_1(100) inner_factorial_1(100) CPU times: user 19.7 s, sys: 12 ms, total: 19.7 s Wall time: 19.7 s

    作者回复: 这个case by case,需要注意的是有些时候一些validation check的cost很高,比如机器学习里面我们会对训练数据(>= 1000 million的样本)做一些统计等等

    2019-05-29
    2
  • MickeyW
    python里的闭包也会跟javaScript里的闭包一样,有内存得不到释放的问题么?

    作者回复: 有可能,stackoverflow上有相关的讨论:https://stackoverflow.com/questions/2017381/is-it-possible-to-have-an-actual-memory-leak-in-python-because-of-your-code

    2019-12-28
    1
  • Geek_5c241c
    MIN_VALUE = 1 MAX_VALUE = 10 def validation_check(value): MIN_VALUE = 3 validation_check(1) print(MIN_VALUE) 仍然是1而不是文章里面说的3,是不是弄错了?

    作者回复: 你仔细看文章,文章里说的是函数内部的MIN_VALUE是3,因为函数内部局部变量覆盖了全局变量。 你如果如果在函数外部打印当然是1。

    2019-05-29
    1
  • rogerr
    连接数据库的密码信息虽然在嵌套的函数里,但对于脚本来说还是明文的

    作者回复: 我这里只是举例说明。实际会做hash,或者通过token之类的其他方式访问

    2019-05-29
    1
收起评论
显示
设置
留言
78
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部