分享

Python 学习之路四

 Four兄 2019-08-30

目录

函数

调用函数

数据类型转换

定义函数

空函数

参数检查

返回多个值

函数的参数

位置参数

默认参数

可变参数

关键字参数

命名关键字参数


继 'Python 学习之路三':

函数

调用函数

Python 内置了很多有用的函数,我们可以直接调用。

要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数 abs,只有一个参数。可以直接从 Python 的官方网站查看文档:

https://docs./3/library/functions.html

官网 3.7.2 版本内置函数汇总(截图):

也可以在交互式命令行通过 help(abs)查看 abs 函数的帮助信息。调用 abs 函数:

  1. >>> abs(100)
  2. 100
  3. >>> abs(-100)
  4. 100
  5. >>> abs(12.12)
  6. 12.12
  7. >>>

调用函数的时候,如果传入的参数数量不对,会报 TypeError 的错误,并且 Python 会明确地告诉你:abs()有且仅有 1 个参数,但给出了两个:

  1. >>> abs(11,22)
  2. Traceback (most recent call last):
  3. File '<pyshell#114>', line 1, in <module>
  4. abs(11,22)
  5. TypeError: abs() takes exactly one argument (2 given)
  6. >>>

如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报 TypeError 的错误,并且给出错误信息:str 是错误的参数类型:

  1. >>> abs('a')
  2. Traceback (most recent call last):
  3. File '<pyshell#117>', line 1, in <module>
  4. abs('a')
  5. TypeError: bad operand type for abs(): 'str'
  6. >>>

数据类型转换

Python 内置的常用函数还包括数据类型转换函数,比如 int()函数可以把其他数据类型转换为整数:

  1. >>> int('321')
  2. 321
  3. >>> int(32.1)
  4. 32
  5. >>> float('12.12')
  6. 12.12
  7. >>> str(12.12)
  8. '12.12'
  9. >>> bool(1)
  10. True
  11. >>> bool(' ')
  12. True
  13. >>> bool(6)
  14. True
  15. >>>

函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:

  1. >>> a = abs
  2. >>> a(-1)
  3. 1
  4. >>>

定义函数

在 Python 中,定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。

自定义一个求绝对值的 my_abs 函数:

  1. >>> def my_abs(x) :
  2. if x >= 0 :
  3. return x
  4. else :
  5. return -x
  6. >>> print(my_abs(-9))
  7. 9
  8. >>>

请注意,函数体内部的语句在执行时,一旦执行到 return 时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。如果没有 return 语句,函数执行完毕后也会返回结果,只是结果为 None。return None可以简写为 return。

如果你已经把 my_abs()的函数定义保存为 abstest.py 文件了,那么,可以在该文件的当前目录下启动 Python 解释器,用 from abstest import my_abs 来导入 my_abs()函数,注意 abstest 是文件名(不含.py 扩展名):

  1. >>> from abstest import my_abs
  2. >>> my_aba(-9)
  3. -9
  4. >>>

空函数

如果想定义一个什么事也不做的空函数,可以用 pass 语句:

  1. >>> def nop():
  2. pass
  3. >>>

pass 语句什么都不做,那有什么用?实际上 pass 可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个 pass,让代码能运行起来。pass 还可以用在其他语句里,比如:

  1. >>> if age >= 20 :
  2. pass
  3. (缺少了 pass,代码运行就会有语法错误。)

参数检查

调用函数时,如果参数个数不对,Python 解释器会自动检查出来,并抛出TypeError:

  1. >>> abs('a')
  2. Traceback (most recent call last):
  3. File '<pyshell#117>', line 1, in <module>
  4. abs('a')
  5. TypeError: bad operand type for abs(): 'str'
  6. >>>

返回多个值

函数可以返回多个值吗?答案是肯定的。比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标:

  1. >>> import math
  2. >>> def move(x,y,step,angle=0):
  3. nx = x + step * math.cos(angle)
  4. ny = y - step * math.sin(angle)
  5. return nx,ny
  6. >>> x,y = move(100,100,60,math.pi/6)
  7. >>> print(x,y)
  8. 151.96152422706632 70.0
  9. >>>

但其实这只是一种假象,Python 函数返回的仍然是单一值:

  1. >>> m = move(100,100,60,math.pi/6)
  2. >>> print(m)
  3. (151.96152422706632, 70.0)

原来返回值是一个 tuple!但是,在语法上,返回一个 tuple 可以省略括号,而多个变量可以同时接收一个 tuple,按位置赋给对应的值,所以,Python 的函数返回多值其实就是返回一个 tuple,但写起来更方便。

函数的参数

定义函数的时候,把参数的名字和位置确定下来,函数的接口定义就完成了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。Python 的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。

位置参数

  1. >>> def power(x) :
  2. return x * x
  3. >>> power(3)
  4. 9
  5. >>>

对于 power(x)函数,参数 x 就是一个位置参数。当我们调用 power 函数时,必须传入有且仅有的一个参数 x:

那么,可以把 power(x)修改为 power(x, n),用来计算 x的n次方:

  1. >>> power(5,2)
  2. 5
  3. >>> def power(x,n):
  4. s = 1
  5. while n > 0 :
  6. n = n -1
  7. s = s*x
  8. return s
  9. >>> power(5,2)
  10. 25
  11. >>> power(3,5)
  12. 243
  13. >>>

修改后的 power(x, n)函数有两个参数:x 和 n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数 x 和 n。

默认参数

新的 power(x, n)函数定义没有问题,但是,旧的调用代码失败了,原因是我们增加了一个参数,导致旧的代码因为缺少一个参数而无法正常调用:

  1. >>> power(2)
  2. Traceback (most recent call last):
  3. File '<pyshell#189>', line 1, in <module>
  4. power(2)
  5. TypeError: power() missing 1 required positional argument: 'n'
  6. >>>

Python 的错误信息很明确:调用函数 power()缺少了一个位置参数 n。这个时候,默认参数就排上用场了。由于我们经常计算 x2,所以,完全可以把第二个参数 n 的默认值设定为 2:

  1. >>> def power(x,n = 2):
  2. s = 1
  3. while n > 0:
  4. n = n - 1
  5. s = s * x
  6. return s
  7. >>> power(2)
  8. 4
  9. >>> power(2,5)
  10. 32
  11. >>>

从上面的例子可以看出,默认参数可以简化函数的调用。设置默认参数时,有几点要注意:

  • 一是必选参数在前,默认参数在后,否则 Python 的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
  • 二是如何设置默认参数。

当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。使用默认参数有什么好处?最大的好处是能降低调用函数的难度。

可变参数

在 Python 函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是 1 个、2 个到任意个,还可以是 0 个。

以数学题为例子,给定一组数字 a,b,c……,请计算 a2 + b2 + c2 + ……。要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,首先想到可以把a,b,c……作为一个 list 或 tuple 传进来,这样,函数可以定义如下:

  1. >>> def calc(nums):
  2. sum = 0
  3. for n in nums:
  4. sum = sum + n * n
  5. return sum
  6. >>> calc([1,2,3,4])
  7. 30
  1. >>> def calc(*num):
  2. sum = 0
  3. for n in num:
  4. sum += n * n
  5. return sum
  6. >>> calc (1,2)
  7. 5
  8. >>> calc(3)
  9. 9
  10. >>>

定义可变参数和定义一个 list 或 tuple 参数相比,仅仅在参数前面加了一个*号。在函数内部,参数 numbers 接收到的是一个 tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括 0 个参数:

  1. >>> calc (1,2)
  2. 5
  3. >>> calc(3)
  4. 9
  5. >>> calc()
  6. 0
  7. >>>

*nums 表示把 nums 这个 list 的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。

关键字参数

可变参数允许你传入 0 个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入 0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个 dict。

  1. >>> def person(name,age,**kg):
  2. print('name:',name,'age:',age,'other',kg)
  3. >>> person('Jerry',20)
  4. name: Jerry age: 20 other {}
  5. >>> person('Jerry',20,city='shanghai')
  6. name: Jerry age: 20 other {'city': 'shanghai'}
  7. >>>

函数 person 除了必选参数 name 和 age 外,还接受关键字参数 kg。在调用该函数时,可以只传入必选参数:

  1. >>> person('Jerry',20,city='shanghai',job='Enginner')
  2. name: Jerry age: 20 other {'city': 'shanghai', 'job': 'Enginner'}
  3. >>>

关键字参数有什么用?它可以扩展函数的功能。比如,在 person 函数里,保证能接收到 name 和 age 这两个参数,但是,如果调用者愿意提供更多的参数,也能收到。试想正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。

**extra 表示把 extra 这个 dict 的所有 key-value 用关键字参数传入到函数的**kw 参数,kw 将获得一个 dict,注意 kw 获得的 dict 是 extra 的一份拷贝,对 kw 的改动不会影响到函数外的 extra。

命名关键字参数

(待整理)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多