Py学习  »  Python

零基础学习 Python 之函数

Python空间 • 5 年前 • 367 次点击  
阅读 36

零基础学习 Python 之函数

写在之前

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

函数是什么?

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

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

如果你理解了这些,我们下面用纯粹的中学的数学方式,在 Python 中建立函数:

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

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

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

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

如何定义函数?

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

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

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

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

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

  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空间」,期待和你的交流。

在这里插入图片描述


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/LHkeHOEiiG
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/27435
 
367 次点击