Python必备之函数

发布时间:2021-12-03 公开文章

 

 

 

 

着手开始写的时候就一直有一个画面在脑子中出现:小猪佩奇第N级,猪爸爸拿出来一本《混凝土的故事》,打开书的时候说道:混凝土是由砂子、水、水泥组成的,结果其他人都睡着了。于是,我在想,要是给土木人讲:python万法皆对象,对象类型有:





 

  • 数字:int,long,float,complex,bool
  • 字符:str,unicod
  • 列表:list
  • 字典:dict
  • 元组:tuple
  • 文件:file
  • 其他类型:集合(set),冻结集合(frozenset),类类型等。

是不是也有人睡着?相反,如果我直接说砂子、水泥、钢筋、混凝土,是不是觉得亲切?所以接下来将会从一砖一瓦的建筑材料说Python。
万法皆对象:在基建领域,你所看到的构筑物就是有以上提到的基础建材组成;在Python领域对象类型就可以看做基础建筑材料,然后由不同的施工工艺产生不同的单体模块或构造物。例如:一个函数(施工工艺)所包含的参数(基础建材),形成一个伪代码。

伪代码
#围墙条形基础开挖
变量类型:铲子、䦆头、羊角碾、块石、砖头、水泥、混凝土
#工艺流程:
#开挖条形基坑
#夯实基础
#抛填块片石
#混凝土填充找平
#砌砖
#如果基坑挖至设计标高,停止开挖;
#如果没有到设计标高,接着开挖。
情况一:
直到设计标高为止(while):
开挖不要停;
情况二:
持续开挖不要停(for):
直到设计标高(if)为止(break):

#本节讲述列表推导式的语法技巧,此法学会,就算入门了!

#伐开心,去年嚷着嚷着讲基础的小伙伴都去哪了,该不都玩都抖音去了?

真代码
 

函数

定义函数

函数function,通常接受输入参数,并有返回值。

它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。

def add(x, y):
    """Add two numbers"""
    a = x + y
    return a

函数通常有一下几个特征: - 使用 def 关键词来定义一个函数。 - def 后面是函数的名称,括号中是函数的参数,不同的参数用 , 隔开, def foo(): 的形式是必须要有的,参数可以为空; - 使用缩进来划分函数的内容; - docstring 用 """ 包含的字符串,用来解释函数的用途,可省略; - return 返回特定的值,如果省略,返回 None 。

使用函数

使用函数时,只需要将参数换成特定的值传给函数。

Python并没有限定参数的类型,因此可以使用不同的参数类型:

print(add(2, 3))
print(add('foo', 'bar'))
5
foobar

在这个例子中,如果传入的两个参数不可以相加,那么Python会将报错:

print(add(2, "foo"))
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-3-6f8dcf7eb280> in <module>()
----> 1 print add(2, "foo")


<ipython-input-1-e831943cfaf2> in add(x, y)
      1 def add(x, y):
      2     """Add two numbers"""
----> 3     a = x + y
      4     return a


TypeError: unsupported operand type(s) for +: 'int' and 'str'

如果传入的参数数目与实际不符合,也会报错:

print(add(1, 2, 3))
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-4-ed7bae31fc7d> in <module>()
----> 1 print add(1, 2, 3)


TypeError: add() takes exactly 2 arguments (3 given)
print(add(1))
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-5-a954233d3b0d> in <module>()
----> 1 print add(1)


TypeError: add() takes exactly 2 arguments (1 given)

传入参数时,Python提供了两种选项,第一种是上面使用的按照位置传入参数,另一种则是使用关键词模式,显式地指定参数的值:

print(add(x=2, y=3))
print(add(y="foo", x="bar"))
5
barfoo

可以混合这两种模式:

print(add(2, y=3))
5

设定参数默认值

可以在函数定义的时候给参数设定默认值,例如:

def quad(x, a=1, b=0, c=0):
    return a*x**2 + b*x + c

可以省略有默认值的参数:

print(quad(2.0))
4.0

可以修改参数的默认值:

print(quad(2.0, b=3))
10.0
print(quad(2.0, 2, c=4))
12.0

这里混合了位置和指定两种参数传入方式,第二个2是传给 a 的。

注意,在使用混合语法时,要注意不能给同一个值赋值多次,否则会报错,例如:

print(quad(2.0, 2, a=2))
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-12-101d0c090bbb> in <module>()
----> 1 print quad(2.0, 2, a=2)


TypeError: quad() got multiple values for keyword argument 'a'

接收不定参数

使用如下方法,可以使函数接受不定数目的参数:

def add(x, *args):
    total = x
    for arg in args:
        total += arg
    return total

这里,*args 表示参数数目不定,可以看成一个元组,把第一个参数后面的参数当作元组中的元素。

print(add(1, 2, 3, 4))
print(add(1, 2))
10
3

这样定义的函数不能使用关键词传入参数,要使用关键词,可以这样:

def add(x, **kwargs):
    total = x
    for arg, value in list(kwargs.items()):
        print("adding ", arg)
        total += value
    return total

这里, **kwargs 表示参数数目不定,相当于一个字典,关键词和值对应于键值对。

print(add(10, y=11, z=12, w=13))
adding  y
adding  z
adding  w
46

再看这个例子,可以接收任意数目的位置参数和键值对参数:

def foo(*args, **kwargs):
    print(args, kwargs)

foo(2, 3, x='bar', z=10)
(2, 3) {'x': 'bar', 'z': 10}

不过要按顺序传入参数,先传入位置参数 args ,在传入关键词参数 kwargs 。

返回多个值

函数可以返回多个值:

from math import atan2

def to_polar(x, y):
    r = (x**2 + y**2) ** 0.5
    theta = atan2(y, x)
    return r, theta

r, theta = to_polar(3, 4)
print(r, theta)
5.0 0.927295218002

事实上,Python将返回的两个值变成了元组:

print(to_polar(3, 4))
(5.0, 0.9272952180016122)

因为这个元组中有两个值,所以可以使用

r, theta = to_polar(3, 4)

给两个值赋值。

列表也有相似的功能:

a, b, c = [1, 2, 3]
print(a, b, c)
1 2 3

事实上,不仅仅返回值可以用元组表示,也可以将参数用元组以这种方式传入:

def add(x, y):
    """Add two numbers"""
    a = x + y
    return a

z = (2, 3)
print(add(*z))
5

这里的*必不可少。

事实上,还可以通过字典传入参数来执行函数:

def add(x, y):
    """Add two numbers"""
    a = x + y
    return a

w = {'x': 2, 'y': 3}
print(add(**w))
5

map 方法生成序列

可以通过 map 的方式利用函数来生成序列:

def sqr(x): 
    return x ** 2

a = [2,3,4]
print(list(map(sqr, a)))
[4, 9, 16]

其用法为:

map(aFun, aSeq)

将函数 aFun 应用到序列 aSeq 上的每一个元素上,返回一个列表,不管这个序列原来是什么类型。

事实上,根据函数参数的多少,map 可以接受多组序列,将其对应的元素作为参数传入函数:

def add(x, y): 
    return x + y

a = (2,3,4)
b = [10,5,3]
print(list(map(add,a,b)))
[12, 8, 7]




土木狗的视角:函数算是基础学习的阶段性成果,过了这个门槛,在import的世界里可以狗刨了。这么说函数,就是用前面的基础材料形成一套标准工艺流程,仍旧说混凝土试块的制作,函数就是模具,你添加一定的原材料,他给你产出预期的产品(返回)。鉴于人气一般,系列基础到此为止,类对象?匿名函数?算了吧,反正也没有人看,你自己百度吧。

课后作业(可选)
按上一节运行自己的项目,新建一个*.ipynb文件,将上面代码敲入运行。