零基础学习 Python 之函数

写在以前

今天咱们又开始了新的篇章 -- 函数篇,在现代的任何科技门类,乃至于政治学,经济学等都已经广泛使用函数,能够说函数的出现直接的加快了现代科技和社会的发展,下面就开始咱们与 Python 中的函数的初次相见吧。python

函数是什么?

在咱们学生时代的数学中,定义函数的方式通常是这样的:y = ax + b,这是一个一次函数,固然咱们也能够写成 f(x) = ax + b,其中 x 是变量,能够表明任何数,可是这个并非函数的所有,在函数中,其实变量并无规定只能是数,它能够是猪狗牛羊,也能够是花鸟木鱼,说到这不知道你有没有理解个人意思,其实,函数就是一种映射。git

若是你尝试着将变量 x 理解为小猪佩奇,那么 ax + b 就是 a 个佩奇再加上 b,这个结果对应着的是另外一个东西,好比熊大,即咱们能够理解为 a 个佩奇加上 b 就对应的是熊大,这就是咱们所说的映射关系。编程

若是你理解了这些,咱们下面用纯粹的中学的数学方式,在 Python 中创建函数:bash

>>> x = 6
>>> y = 2 * x + 1
>>> y
13
复制代码

在咱们的学生时代咱们就是这么用的,那么在 Python 中这种方式还有用吗?上面的例子咱们创建了一个所谓的函数,那么咱们来尝试改变一下 x 的值:app

>>> x = 7
>>> y
13
复制代码

结果是 y 的值并无改变,因此说用纯粹的数学方式定义函数在 Python 中其实并无什么用,因此咱们要用一种新的定义函数的方式,请接着向下看。ssh

如何定义函数?

在 Python 中定义了函数的格式,下面我举一个例子来讲一下 Python 中函数的格式和调用的方法:函数

>>> def add(x,y):
...    return x + y
复制代码

上面的例子虽然短小,但内有乾坤,下面我以此函数为例,详述函数的组成。学习

  1. def :def 是函数的开始,也就是在声明要建立一个函数的时候,必定要先使用 def,这就是告诉 Python 解析器,这里要声明的是一个函数。ui

  2. add:add 是函数的名称,在 Python 中起名字的讲究就是要起的有意义,能从函数的名字上看出这个函数是干什么的。同时函数的命名规范和变量名是同样的,必须使用字母和下划线开头,且仅能含有字母,数字和下划线。this

  3. ( x,y ):这个是参数列表,要写在括号里,其中的参数指向函数的输入,本例中函数有两项输入,可是一般状况下,输入的个数能够是任意的,也包括 0 个。

  4. : :冒号很是重要,若是少了,会报错,因此但愿大家不要像我同样。

  5. return a + b:这一行,就是函数体了,函数体是缩进了 4 个空格的代码块,完成你须要完成的工做。 return 是函数的关键字,意思是要返回一个值,函数中的 return 也不是必需要写的,若是不写的话, Python 会默认返回一个值,那就是 None。

调用函数

在这以前,咱们想一下咱们为何要写函数?理论上来讲,不用函数也能够写代码,之因此用函数,大佬们给咱们总结了如下几点,我在这借花献佛:

  1. 写函数能够下降编程的难度。一般将一个复杂的大问题分解成一系列更小的问题,而后小问题再分解成更小的问题,当问题细化到足够简单时,就能够分而治之。

  2. 代码重用。其实咱们在编程的时候比较忌讳同一段代码不断重复,所以有必要将某个经常使用的功能抽象为一段公用的代码,也就是函数。

从上面来看,使用函数仍是颇有必要的,下面就来看看函数是怎么调用的:

>>> def add(x,y):
...    print('x = {}'.format(x))
...    print('y = {}'.format(y))
...    return x + y
复制代码

咱们把以前的例子稍做改变,而后接下来看:

>>> add(10,3)
x = 10
y = 3
13
>>> add(3,10)
x = 3
y = 10
13
复制代码

函数调用,最关键的是要弄懂如何给函数的参数赋值,上面就是按照参数次序赋值,根据参数的位置,值与之相对应。

>>> add(x = 3,y = 10)
x = 3
y = 10
13
>>> add(y = 10,x = 3)
x = 3
y = 10
13
复制代码

还能够像上面同样直接把赋值语句写到里面,这就明确了参数和对象的关系,这个时候顺序就不重要了。

固然还能够在定义函数的时候就赋给一个默认值,若是不给那个有默认值的参数赋值,那么它就用默认值,若是给它传一个,则采用新传给它的值:

>>> def add(x,y = 1):
...    print('x = {}'.format(x))
...    print('y = ',y)
...    return x + y
... 
>>> add(1)
x = 1
y =  1
2
>>> add(1,1000000)
x = 1
y =  1000000
1000001
复制代码

在这里想在强调一次,参数和对象的关系与变量和对象的关系同样,即在函数中的参数所传的都是对象的引用,而不是对象自己

函数是颇有深度的,须要咱们深刻探究,实践过程当中,有不少对函数的不一样理解,须要咱们在学习的过程当中不断的思考,下面咱们学习一些函数的相关应用。

返回值

所谓的返回值,就是在调用函数的地方由函数返回的数据。下面咱们用咱们最熟悉的斐波那契数列为例,咱们编写一个函数来实现斐波那契数列:

>>> def fibs(n):
...    res = [0,1]
...    for i in range(n-2):
...            res.append(res[-2] + res[-1])
...    return res
... 
>>> if __name__ == "__main__":
...    now = fibs(10)
...    print(now)
...
复制代码

在上面的代码中咱们首先定义了一个函数,名字叫作 fibs,参数是输入一个整数(其实你输入非整数也是能够的,只是结果不一样),而后经过 now = fibs(10) 调用这个函数。这里的参数给的是 10,这就觉得着要获得的是 n = 10 的斐波那契数列。运行之后的结果以下 :

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
复制代码

固然若是你想换 n 的值,只须要在调用的时候修改一下参数就行了。而后咱们来观察上面的函数,最后有一个语句 return res,意思是将 res 的值返回,可是返回给谁呢?这要看是在什么位置调用的函数。在上面的代码中,用 now = fibs(10) 调用了函数,那么函数就将值返回到当前状态,并记录在内存中,而后把它赋值给变量 now。

须要注意的,上面虽然返回的是列表,但其实只是返回了一个返回值,有时候咱们须要返回多个的时候,要用元组的方式。

>>> def my_digit():
...    return 1,2,3
... 
>>> now = my_digit()
>>> now
(1, 2, 3)
复制代码

对于上面的这个函数,其实咱们还能够像下面同样:

>>> x,y,z = my_digit()
>>> x
1
>>> y
2
>>> z
3
复制代码

并非因此的函数都有 return,好比某些函数就只是执行一条语句或者干脆什么也不作,它们不须要返回值,其实看过昨天文章的朋友可能会有印象,其实它们也有,只不过是 None。好比下面的函数:

>>> def cau():
...    pass
... 
>>> now = cau()
>>> print(now)
None
复制代码

这个函数的做用就是什么也不作,固然也就不须要 return。

咱们能够特别注意一下那个 return,它其实还有一个做用,请看下面的例子:

>>> def my_info():
...    print('my name is rocky')
...    return
...    print('i like python')
... 
>>> my_info()
my name is rocky
复制代码

看出什么了吗?明明有两个 print,在中间插入一个 return 之后,只执行了第一个 print,第二个并无执行。这是由于在第一个以后遇到 return,它告诉函数要终端函数体内的流程,因此 return 在这里的做用就是:结束正在执行的流程,并离开函数体返回到调用的位置。

函数的文档

函数的文档,通常是写在函数的名字下面,说明这个函数的用途,由于这个我感受很重要,以前虽然也说过注释的重要性,但仍是感受有必要再次说明。

def fibs(n):
 """ 这是一个求斐波那契数列的函数 """
复制代码

在函数的下面,用三对引号的方式包裹着这个函数文档,也叫函数的说明。

好比咱们用 dir 来查看函数对象,好比 dir(type),咱们会看到 doc,这个就是文档:

>>> dir(type)
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__prepare__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__', '__weakrefoffset__', 'mro']
>>> type.__doc__
"type(object_or_name, bases, dict)\ntype(object) -> the object's type\ntype(name, bases, dict) -> a new type"
复制代码

若是上面的例子在交互模式下的话,用 help(fibs),获得的也是三对引号所包裹的文档信息,感兴趣的能够尝试一下。

函数的属性

任何对象都具备属性,咱们前面的文章说过函数是对象,那么函数也有属性。

>>> def cau():
...    """this is a cau function"""
...    pass
...
复制代码

对于上面的函数,最熟悉的属性应该就是上面提到的函数文档 doc,它能够用英文句号的方式表示为 cau.__doc__

>>> cau.__doc__
'this is a cau function'
复制代码

这就能体现出这种方式表示函数属性的优点,只要对象不一样,无论你属性的名字是否相同,用英文句号均可以说明属性所对应的对象。

咱们还能够给对象增长属性,好比咱们给 cau 增长一个 pig 属性,并设置为 100,顺便咱们再调用一下它:

>>> cau.pig = 100
>>> cau.pig
100
复制代码

还记得上面我说的那个查看对象属性和方法的 dir 吗?如今有请它闪亮登场:

>>> dir(cau)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'pig']
复制代码

在这里列出了全部 cau 这个函数对象的属性和方法,仔细观察咱们会发现,咱们刚用过的 doc 和咱们新增长的 pig 都在其中,至于你在纠结那些名字先后都是用双下划线的,你暂且能够把它们称之为特殊属性,全部的这些属性都是能够用英文句点的方式调用,感兴趣的能够试一试。

写在以后

更多内容,欢迎关注公众号「Python空间」,期待和你的交流。

在这里插入图片描述
相关文章
相关标签/搜索