轻松初探Python(六)—函数

这是「AI 学习之路」的第 6 篇,「Python 学习」的第 6 篇

题外话

这周工作日 5 天,我并没有更新文章,但大家并不要以为小之懒惰了。正好相反,自从上篇的 AI 入门文章后,我自己便开始进行机器学习的系统学习了,这周一到周五,只要有空闲时间,我就开始看吴恩达 Coursera 的视频,可以说是非常痴迷了。

吴教授的课程非常通俗易懂,而且他本人的教学风格也是不紧不慢,循序渐进,甚至有关微积分和线代甚至 Octave 这些知识点都花了比较多的篇幅进行展开讲解,亲身体会后,再次推荐给大家。

目前,机器学习篇我已经学到一半了,实际上本来可以更快一些,但中间的一些微积分和线代的知识点,我又回炉复习了一下。非常庆幸我在大四的时候把高数重新复习了一遍,现在虽说不能完全回想起来,但回炉和记忆的串联算是比较快的,节省了很多的时间。

同时,我现在每天保持一到两题的 LeetCode 刷题量,实际上我不太追求说要刷的多快,刷题的目的一来是巩固基础,二来是每天刷一两道,活动下脑子。我每天早上上班前,先打开一道题,然后把题目阅读一下,过个脑子,上班途中就想想思路,如果思路比较清晰,到公司在别人吃早饭的时间,我就把代码提交了,如果思路不太顺,我就工作空闲或者中午的时候在桌上用纸笔画一画,然后晚上下班之后开始码代码。

如果这样的流程一天时间还是想不起来思路,那我就会直接看一下 discuss 或者 Solution,不追求必须靠自己解答出来,只要学到方法,过个脑子,然后把代码码出来上传到 GitHub 留个记录,对我来说就够了。

好了,回归正题,今天我们来较为细致的讲解下 Python 中的函数。

函数的定义

我们之前已经看了很多函数的使用例子了,比如我们要定义一个函数可以这样写

我们来看看这段代码。通过 def 语句,依次写出函数名、括号、括号中的参数,还有最后的冒号,千万不要忘记了。

冒号后面,就是具体的函数体了,函数体第一行和函数定义要有一个 Tab 的缩进距离。我们知道 Python 是没有分号和大括号来区分代码的结束和开始的,所以缩进的问题一定要注意,如果你的缩进不正确,可能会报 indented 错误。

在交互式环境下定义函数的时候,冒号输入完毕回车后,会有 ... 的提示,每行结束回车到下一行,连续两次回车定义该函数完毕,重新回到 >>> 提示符下。

Python 是一门面向对象语言,一切都是对象,甚至函数本身也是对象,我们称这种特性为「函数式编程」,上面的例子中,我们直接打印 testFun 是可以打印出它的函数类型的。

像我们熟悉的 Kotlin、Groovy 还有 Go 语言,都有这样的特性,函数式编程可以有非常强大的拓展性,同时可以很轻易的解决很多不支持函数式编程的语言下的一些写法问题。这个我会在后面专门写一篇文章来介绍 Python 的函数式编程。

使用函数很简单, 函数名、括号,加上参数即可调用函数。因为 Python 是动态类型语言,所以我们不需要像 Java 那样,对每一个变量和方法参数都提前在编译期设置好类型,我们定义 testFun(a) 的时候,并没有指示 a 到底是字符串类型还是别的类型。这样的自由肯定是有一定代价的,当函数体内部对参数的使用有较严格的要求的时候,如果传参类型错误,就会报错。

函数的参数

函数的定义不是很复杂,但搭配参数,就会非常灵活,Python 的参数五花八门,除了我们常用的位置参数外,还有默认参数、可变参数和关键字参数。

位置参数

我们之前定义的 testFun(a) 中的 a 就是一个位置参数,当然你可以设置很多位置参数,顾名思义,参数的意义是和位置一一对应的,比如我们现在改写下 testFun 让它具备输出两个参数的能力

刚刚说的位置一致性的意思就是我们的输入参数的顺序是和函数定义时候的参数顺序是一致的,第一个参数是'测试',第二个参数是'参数',只能代表 a='测试',b='参数',顺序不能错乱。

默认参数

Java 中,如果需要使用一个函数的多种参数形式,是通过重载的形式的,这种方式是比较麻烦的,比如,上面的例子中,我们想让 testFun 既可以使用一个参数,也可以使用两个参数

在 Python 中,我们可以使用默认参数来一次性完成这样的函数定义

使用 testFun(a) 的时候,会自动把 b 赋值为 '函数',只有当你需要改变 b 的时候,才需要自己输入参数值。需要注意的是,默认参数定义要放在位置参数的后面。

不仅如此,默认参数的默认值一定要指向的是不可变对象,否则就会出现一些难以预料的问题,这里举一个例子

注意到了吗,虽然我们的默认参数 L 是一个空 list,但在调用的过程中,每次添加元素,都会被添加到 L 这个 list 中去,而不是我们预料的那样,每次都是一个新的单元素 list,所以我们的默认参数,尽量使用不可变对象,除非你的设计逻辑就是如此。

可变参数

默认参数虽然可以拓展函数的参数数量,但毕竟数量还是固定的,如果我们想让参数数量是任意的,可以使用可变参数,可变参数很简单,在参数前加 * 号即可

我们也可以把 list 和 tuple 加星号传入可变参数中

关键字参数

关键字参数和可变参数一样,可以允许你传入 0 到任意个参数,不过这些参数都是含有参数名的,在函数内部是以一个 dict 的形式组装

当然,你可以像可变参数那种形式一样,通过提前定义好 dict,再把变量以 ** 开头传入。

关键字参数比较随意,你可以传入不受限制的参数,如果你需要判断传了哪些参数,你还需要在函数体内部进行判断,这个时候,我们就可以用命名关键字参数来作一定的限制

命名关键字参数需要一个分隔符 * ,* 号后面就会被看作是命名关键字参数。如果定义中有一个可变参数,那么后面的命名关键字参数就不需要 * 了,就像这样

命名关键字参数是可以有默认值的,有默认值的情况下,可以不传入该参数,这点和默认参数有点类似

参数的组合

Python 中,上述参数可以组合使用,但需要注意一定的顺序:必选位置参数、默认参数、可变参数、命名关键字参数、关键字参数,这部分我将用廖大的例子来简单介绍下,我们先定义两个有若干参数的函数:

调用的时候,Python 解释器会自动按照参数位置和参数名把对应参数穿进去

最神奇的是可以通过一个 tuple 和 dict 完成上述函数的调用

所以我们可以通过类似 func(*args, **kw) 的形式来调用任意函数,无论它的参数是如何定义的。你去翻看源码,可以看到很多内置的函数都是用这种形式定义函数的。

本文来自企鹅号 - 全球大搜罗媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员互动联盟

【答疑解惑】java中switch语句陷阱

语音版: 今天群中小伙伴们遇到了一个switch问题我给大家讲解一下,算是Java中的小陷阱吧。 Java中的switch语句穿透: 今天一同学写了类似下面的代...

3447
来自专栏智能合约

PHP魔术方法之__set()和__get()

1193
来自专栏WeaponZhi

轻松初探Python(六)—函数

这是「AI 学习之路」的第 6 篇,「Python 学习」的第 6 篇 题外话 这周工作日 5 天,我并没有更新文章,但大家并不要以为小之懒惰了。正好相反,自从...

3327
来自专栏从零开始学自动化测试

python笔记20-获取当前运行函数名

写完代码之后,一般为了方便查看日志,可以在日志输出中加入当前运行的函数名称或类和方法名称,以便于代码报错的时候能快速找到报错的是哪个函数或方法。 那么如何获取当...

761
来自专栏武军超python专栏

2018年7月22日用python写个人博客时遇到的问题

今天遇到的新单词: subscript  n下标,脚注 integer    n整数,整型 function   n函数 variable   n变量 ...

682
来自专栏Python小屋

微课系列(一):Python列表remove()方法工作原理

1)在列表非尾部增加或删除元素时,该位置后面元素会向后移动或向前移动,保证元素之间没有缝隙,这样的话,这些元素的索引会发生变化。

714
来自专栏搞前端的李蚊子

JS——判断一个对象是否为空

判断一个对象是否为空对象,本文给出三种判断方法: 1.最常见的思路,for...in...遍历属性,为真则为“非空数组”;否则为“空数组” ?  2.通过JSO...

3458
来自专栏mySoul

DOM概述 选取文档元素

有些html标签会有name元素,区别于id,name属性的值不必是唯一的,多个元素可能存在相同的名字。

836
来自专栏java沉淀

判断两个Integer值相等为什么不用==

681
来自专栏zingpLiu

Web模板引擎本质前奏

我了个擦,居然把字符串变成了函数并且还为该函数提供了全局变量,是不是很巧秒。这个功能其实就是python的web框架中模板语言部分至关重要的部分,因为在模板处理...

844

扫码关注云+社区