技术 | Python从零开始系列连载(十三)

Python特色数据类型(函数)

1

函数

说到函数,如果你没有编程基础,可能马上会想到初高中学过的:

y = f(x)

例如:y = x +1

当我们 x = 1时,y = 2

x = 2,y = 3

小明:老湿,我们不是初中生!

函数可以将问题简化,我们可以重复使用这个函数解决 y = x + 1 这一类问题

所以,函数就是那些做成重复使用的程序代码

2

函数的定义

函数是由函数名、参数和函数体组成,格式如下:

def 函数名(形式参数):

函数体

[ return 返回值 ]

def是系统关键字,之后的文章会系统讲一下,这里只要知道这个是用来定义函数的

如果是你自己定义函数,函数名要符合变量命名规则,并且不能是系统关键字(在jupyter中,打出系统关键字是绿色的)

例如,我们定义一个求两个数的和的函数:

看,这里的 def 和 return 是绿色的,也就是系统关键字

这里函数名是add(英语是求和的意思)

然后有两个形式参数,a和b

函数体部分执行的是 c = a +b

最后函数返回的是 c 的值

这就完成了一个求和函数的定义

3

函数的调用

函数的调用很简单,我们只要根据函数的定义形式

将实际计算时的参数值传进去就行(也可能没有参数)

函数调用格式:

函数名(实际参数)

这里的 add(3,4) 就是函数调用

实际参数分别是 3 和 4

当函数调用发生时,才开始执行函数的内容

即给 a 赋值为 3 , b 赋值为 4

然后计算出 c = 7

最后返回 c 的值 7

函数调用写的参数是实际参数(‘实际’体现在参数是实际执行函数使用的)

函数定义写的参数是形式参数(‘形式’体现在他只是个格式和形式,真正函数执行时候还是先看实际参数)

其实,Python有很多内置函数,例如我们之前课程常常使用的print()

print()函数是内置的,所以不用定义

内置:安装好Python就有的

还记得以前手机很多内置吸费软件么

点进去xxx软妹币就没了,手机短信提示欠费了

4

参数的传递

函数调用时候,是将实际参数传递给形式参数

函数参数的传递方法有很多

1.参数按照位置顺序传递

刚才的add函数就是这种,按顺序,3传递给a,4传递给b

2.参数按赋值传递

这里定义了一个两数相减的函数

注意到函数调用时候,指明了 b = 4 , a = 3

是一种赋值,所以这里的就和上个相加的例子中顺序传递参数不一样了

3.参数按照默认值传递

有时候,可以在函数定义里给函数形参设定一个默认值

当函数实参没有传递值进来,就使用默认值

这里在定义函数时候,给形参 b 设置了默认值 2

然后调用函数时候,只传递了一个参数值 4

则python默认将 4 传递给 a,因为在定义时候给 b 设定了默认值 2

当然,当传入的参数是两个时候,则覆盖掉默认值,即不使用定义时候的默认参数值

4.(难点)元组类型的变长度参数传递

我们写个打印输出的函数

如果我们要打印三个数怎么办?

小明:老湿,我知道!我们可以这样!

小明:

很好!小明,如果我们要打印1000个数呢

小明:emmmm

【敲黑板】

我们可以定义一个变长参数,可长可短,你懂的!【坏笑

小明: 这不是去幼儿园的车!我要下车!

我们可以在参数前面加一个星号 * ,表示这个参数是可变长参数

当其他参数赋值完毕时候,剩下的参数依次赋值给这个可变长参数

所以刚才的可以这样实现:

但是,注意到没有,这里的 b 是元组 (2,3)

所以你执意要打印出,可以提前修改函数的打印功能

这就通用了,不信你试试:

相当于将字典的每个元素依次拿出来

5.(难点)字典类型的变长度参数传递

我们可以在参数前面加两个星号 ** ,表示这个参数是可变长参数

是以 实参名=字典值的方式传递

例如刚才的例子,我们改一下

注意到,字典类型变长参数传递一定是赋值形式传递进去的

当然,元组和字典形式变长参数也可能用不到,例如:

这样,打印出的就是空元祖和空字典啦~

如果你执意要实现那种打印形式,我们就改一下函数:

c [ j ] 指的是打印 j 这个键对应的值,如果不这样写,结果会是这样,打印出的是键:

注意,可变参数的位置一般写在最后,不能乱了顺序,否则会报错!!!

5

无返回值的函数

之前说了好多,都是有返回值的函数,那有没有没返回值的函数呢?

这个可以有!

6

函数中变量的作用域

变量的作用域就是在程序中能对这个变量操作的区域范围

有点像初高中学的函数的定义域

Python允许同名变量的出现

让我们看个例子:

我们调用dayin_outer( )

这里打印的 a 的值是 2

注意的dayin_inner( ) 函数只是定义了,并没有调用,所以不会运行这个dayin_inner( )的函数体

我们稍微修改一下:

这样就可以了

注意到,a变量分别有三次赋值,这里的赋值不是覆盖了,因为他们三个a是在不同的位置

第一个a是在函数外面,我们称之为全局变量(即它的作用域是全局的)

比如我们改一下程序:

这时候,外面的a就打印出来了!

当然,与之相对的,第二个和第三个a就成为局部变量

而且这个dayin_inner( ) 函数是被嵌套在 dayin_outer( ) 中的

值为 1 的 a 的作用范围是dayin_outer( )外层函数中

值为 2 的 a 的作用范围是dayin_outer( )内层函数中

当我们要使用变量时候,现在最近的区域搜索

我们修改一下程序:

当我们把 a = 1 注释掉

则外层函数打印 a 的时候,取的全局变量

因为内层函数的作用域只在内层函数中,不能延伸到外层函数

我们再改一下程序:

把内层函数里的 a 注释掉

则内层函数使用的 a 是外层函数定义的 a

因为,外层函数距离内层函数比全局变量距离内层函数更近

如果外层函数没有定义 a ,则会去取全局变量

是不是又想起了俄罗斯套娃。。。

注意:不要将变量的作用域和变量重复赋值覆盖搞混

我们看个例子:

注意这里全局变量只有一个 a

他的值是 4,因为 0 被覆盖了

7

匿名函数

匿名函数,匿名指的是我们不知道这个函数的名字

当我们使用时候,用lambda来声明匿名函数

这种匿名函数是没有名字的,是临时使用的

格式:

函数对象名 = lambda 形式参数:表达式

我们演示一下看看:

这里用匿名函数代替了add()函数的功能

x,y是形式参数

x+y是函数体内容

匿名函数也可以有条件分支语句:

返回x和y中较大值

小建议:当函数较为复杂时,不建议匿名函数,不太好写而且结构难理解

8

函数的递归

递归指的是一种直接或者间接调用自身的算法

它的本质是将问题分解为同类型的子问题

还记得高中学数列时候有公式是这样的么:

当我们去求a(n)时候,先要去求a(n-1),然后为了求a(n-1),就先要求a(n-2),以此类推

直到先要求a(1)

然后我们求出a(1),就能返回求出a(2)直到求出a(n)

----------------------end---------------------------

这个函数可以这样写:

有个经典的Fibonacci数列问题

讲的是这样一个故事:

1201年,意大利数学家Fibonacci(斐波那契)发现了以他自己的名字命名的数列---Fibonacci数列。

他是在研究兔子的生长、繁殖的规律中发现这一数列的。

他对数列的研究是从一对刚刚出生的小兔子(雌雄一对)开始计算在n个月后将会有多少只兔子

他做了如下的假设:  

1、新出生的小兔子在一个月的时间里发育为成年兔子;  

2、每对成年兔子每月繁殖一对小兔子(雌雄一对);  

3、兔子没有死亡发生。  

接下来我们来看会产生一组什么样的数呢?  

我们用Fn代表n个月后兔子的对数。

因为从一对新生的兔子开始,所以,F0=1,F1=1。

这一对兔子在第二个月末生出另一对小兔子,从而F2=1+1=2。

在第三个月末,第一对兔子将生下又一对小兔子,所以F3=2+1=3。

我们用如下的表格表示前10个月每个月初兔子的数量:

由此可知,从第一个月开始以后每个月的兔子总数是:

1,1,2,3,5,8,13,21,34,55,89,144,233…  

这就是著名的Fibonacci(斐波那契)数列

这个数列具有这样的特点:前两项均为1,从第三项起,每一项都是其前两项的和

即F0=F1=1,当n>1时,Fn+2=Fn+1+Fn。

我们写成函数是这样的:

使用到了递归的方法!

好啦,这期的分享先到这里,大家可以按照上面的详细步骤进行练习,我们下周五不见不散~

文章来源:Python爱好者社区

文章编辑:小柳

往期文章:

技术 | Python从零开始系列连载(十二)

技术 | Python从零开始系列连载(十一)

技术 | Python从零开始系列连载(十)

技术 | Python从零开始系列连载(九)

技术 | Python从零开始系列连载(八)

技术 | Python从零开始系列连载(七)

技术 | Python从零开始系列连载(六)

技术 | Python从零开始系列连载(五)

技术 | Python从零开始系列连载(四)

技术 | Python从零开始系列连载(三)

技术 | Python从零开始系列连载(二)

技术 | Python从零开始系列连载(一)

原文发布于微信公众号 - 灯塔大数据(DTbigdata)

原文发表时间:2018-04-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小古哥的博客园

读书笔记-JavaScript面向对象编程(一)

前前后后大概花了两周的时间,终于把这本书大致看完了,对之前javascript高级程序设计中模糊不清的概念,有了一些新的看法和角度,整体上来说,本书还是一本比较...

33970
来自专栏Laoqi's Linux运维专列

Python for 循环语句

67080
来自专栏云瓣

ES6的一些常用特性

由于公司的前端业务全部基于ES6开发,于是给自己开个小灶补补ES6的一些常用特性。原来打算花两天学习ES6的,结果花了3天才勉强过了一遍阮老师的ES6标准入门,...

35780
来自专栏机器学习和数学

[编程经验] Python中的continue和break语句

Hi,大家好,国庆结束了,第一天上班感受如何? 今天给大家分享的是Python中的continue和break语句怎么用?continue和break主要是在f...

33970
来自专栏IT派

程序员必知的 Python 陷阱与缺陷列表

我个人对陷阱的定义是这样的:代码看起来可以工作,但不是以你“想当然”的方式。如果一段代码直接出错,抛出了异常,我不认为这是陷阱。比如,Python程序员应该都遇...

12040
来自专栏java学习

Java每日一练(2017/7/21)

聊天系统 ●我希望大家积极参与答题!有什么不懂可以加小编微信进行讨论 ★珍惜每一天,拼搏每一天,专心每一天,成功每一 如果你是初学者,或者是自学者!你可以加小编...

34740
来自专栏CodingBlock

Java数据结构和算法总结-冒泡排序、选择排序、插入排序算法分析

前言:排序在算法中的地位自然不必多说,在许多工作中都用到了排序,就像学生成绩统计名次、商城商品销量排名、新闻的搜索热度排名等等。也正因为排序的应用范围如此之广...

28690
来自专栏GopherCoder

『Go 内置库第一季:reflect』

可以看到,如何获取数据类型,也可以看出 TypeOf 和 Kind 的区别,TypeOf 获取的是基本数据类型和以 type 定义的类型;Kind 获取的是底层...

11240
来自专栏分布式系统和大数据处理

四种简单的排序算法

我觉得如果想成为一名优秀的开发者,不仅要积极学习时下流行的新技术,比如WCF、Asp.Net MVC、AJAX等,熟练应用一些已经比较成熟的技术,比如Asp.N...

14520
来自专栏逸鹏说道

Python3 与 C# 基础语法对比(String专栏)

Python3 与 C# 基础语法对比:https://www.cnblogs.com/dotnetcrazy/p/9102030.html

13530

扫码关注云+社区

领取腾讯云代金券