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

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

你好,我是景霄。
实际工作生活中,我曾见到不少初学者编写的 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 核心技术与实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(77)

  • 最新
  • 精选
  • 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) ```

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

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

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

    3
    5
  • Gfcn
    没想到连闭包都讲,真的是干货满满,32个赞

    作者回复: 谢谢支持

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

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

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

    作者回复: 你说的没错

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

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

    4
    4
  • third
    1.Python中...是啥意思?发现在代码中运行没有错误。也没有百度到 2.#不是说全局变量可以在文件的任意地方都可以被访问吗?,我试了下,去掉x的赋值,就可以访问了。这是什么原因呢? #x=10 def outer(): print(x) x = "local" def inner(): nonlocal x # nonlocal 关键字表示这里的 x 就是外部函数 outer 定义的变量 x x = 'nonlocal' print("inner:", x) inner() print("outer:", x) x=10 outer() #报错Traceback (most recent call last): # File "D:/软件/Python/Lib/idlelib/新p/学习分析/写着玩.py", line 11, in <module> # outer() # File "D:/软件/Python/Lib/idlelib/新p/学习分析/写着玩.py", line 2, in outer # print(x) # UnboundLocalError: local variable 'x' referenced before assignment

    作者回复: 1. 我只是用‘...’表示省略 2. 全局变量在任何地方都可以访问,但是访问之前你必须得定义赋值他啊

    1
  • 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的样本)做一些统计等等

    1
  • 蚊子为什么不咬猫
    正则表达式算吗? r = re.compile('[^\w]') r.match()

    作者回复: 当然是函数,但是这里主要讲自定义哈

  • 拾掇拾掇
    全局声明不可能类型,那么在函数内部只要想全局修改都要加global,所以得出global适合用于不可变类型,因为可变类型不需要也不会报错?

    作者回复: 没明白你的意思,能说的清除一些么?

收起评论
显示
设置
留言
77
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部