连载|想用Python做自动化测试?Python函数入门
“ 函数是 Python 程序中不可或缺的一部分,它是的程序模块化、清晰化。Python的很多功能都是通过内置函数提供的,比如 sorted() 表示对一个集合序列排序,len() 表示返回一个集合序列的长度大小等等。这节课,我们主要来学习 Python 的自定义函数。”
10.1 定义函数
使用def关键字
函数可以有返回值也可以没有返回值
# content of test_sample.pydef inc(x): # 有返回值return x + 1def test_answer(): # 没有返回值assert inc(3) == 5
10.2 调用函数
add_one=inc(3)
函数被调用时,这个函数此前必须定义过
10.3 函数的参数
10.3.1 位置参数
def divmod(x, y): # known case of builtins.divmod""" Return the tuple (x//y, x%y). Invariant: div*y + mod == x. """return (0, 0)
这是一个Python内置的获得商和余数的函数。这个函数有两个参数:x和y,这两个参数都是位置参数,调用这个函数时,要按照顺序传入的两个实参值,实参值会依次赋给参数x和y。
10.3.2 默认值参数
def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):pass
这是Python内置的打开文件的函数,调用open打开文件时,可以只传递file文件路径,其他的参数可以不传递实参值,因为其他的参数都具有默认值。mode是打开文件的模式,默认值是r,表示以读的方式打开文件,默认值参数必须指向不可变对象。
不要这样:
def add_end(li=[]):pass
要这样:
def add_end(li=None):pass
10.3.3 变长参数
可以给函数一次性传递多个参数,或者传递一个列表或元组。定义函数时在参数名前加一个星号*。
def calc(*numbers):sum = 0for n in numbers:sum = sum + n * nreturn sum
函数calc的功能是求任意多个参数的平方和。函数定义时,在参数名加一个星号*。这样的函数,在调用时,可以传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。实际例子如下:
calc(1, 2,3,4)calc(1, 2)calc()nums = [1, 2, 3]calc(*nums) # 还可以传递列表或者元组等进去
max是python内置的求最大值的函数。它的定义如下:
def max(*args, key=None): # known special case of max"""max(iterable, *[, default=obj, key=func]) -> valuemax(arg1, arg2, *args, *[, key=func]) -> valueWith a single iterable argument, return its biggest item. Thedefault keyword-only argument specifies an object to return ifthe provided iterable is empty.With two or more arguments, return the largest argument."""pass
第一个参数是一个变长参数,上面举了两个例子,第一个参数可以是可迭代对象,也可以是多个参数。返回值是多个参数中的最大值,或者可迭代对象中的最大值。比如:
print(max(1, 2, 3, 4, -9, -5)) # 多个参数print(max([1, 2, 3, 4, -9, -5])) # 可迭代对象,这里是一个列表
max函数还有一个默认值参数key,接受一个函数名,这时max函数返回的值是,将args参数分别用到key函数后的结果中的最大值。比如,找出一个数字列表中绝对值最大的元素:
max([1, 2, 3, 4, -9, -5], key=abs)
10.3.4 关键字参数
下面这个sorted函数是Python内置的排序函数,它的第一参数是一个变长参数,第二个参数是个关键字参数,关键字参数是以两个星号开头。
def sorted(*args, **kwargs): # real signature unknown"""Return a new list containing all items from the iterable in ascending order.A custom key function can be supplied to customize the sort order, and thereverse flag can be set to request the result in descending order."""pass
sorted函数默认是升序排序的,可以传入一个关键字参数reverse进行降序排序。方式是:
print(sorted([1, 2, 3, 4, -9, -5], reverse=True))
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个字典。
再来自定义一个:
def person(name, age, **kwargs):print(name,age,kwargs)
关键字参数可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。传递关键字参数有两种方式:
传入字典
extra = {'city': 'Beijing', 'job': 'Engineer'}person('Jack', 24, **extra) # 字典参数名签名放两个**
直接传入key=value
person('Jack', 24, salary=10000, department='finace')
10.3.5 参数组合
定义函数时,参数顺序必须是:位置参数、默认参数、变长参数、关键字参数。定义顺序不能乱。
def f1(a, b, c=0, *args, **kw):pass
10.4 看懂Python源码中函数的定义
有些朋友平时反映,看不懂官方文档中介绍函数的说明,比如查看min的源码:
def min(*args, key=None): # known special case of min"""min(iterable, *[, default=obj, key=func]) -> valuemin(arg1, arg2, *args, *[, key=func]) -> valueWith a single iterable argument, return its smallest item. Thedefault keyword-only argument specifies an object to return ifthe provided iterable is empty.With two or more arguments, return the smallest argument."""pass
min 函数的源码文档中,举了两个例子,其中的形参有 * 符号,又有 []?他们都表示啥意思呢?
函数形参列表中符号 * 表示,后面的形参只能为关键字参数,不能为位置参数,[]里面的参数是可选的,不是必填的,例如传递一个key参数和default参数时,必须写明参数名:
> a = [1,2,3,4,2,2,3,4]> min(a,key=lambda x: a.count(x), default=1) # 求出个数最少的元素1
因为default是可选的,因此还可以这样:
> list=[1,2,5,9,4,6,3]> min(list,key=lambda x:-x) # 取反后最小的值9
再来看一个min函数的用法,求一段文本中出现次数最少的字母。
import stringdef maxcharactor(content):content = content.lower()return min(string.ascii_lowercase, key=content.count)if __name__ == '__main__':print(maxcharactor("/Users/chunming.liu/learn/learn_python_by_coding/learn_string/"))
平时大家更多看到的是这么使用 min 函数,没有key参数:
min([1,2,3,4,2,2,3])
这是因为在min函数说明中,key参数是放在[] 中的,说明它是可选的,可以不传递。
自定义一个函数 func,参数 b 位于 * 后面,只能为关键字参数:
def func(a,*,b):passfunc(a,b=1)f(a,1) # 这种调用是错误的TypeError: f() takes 1 positional argument but 2 were given
再看一个内置函数 sum:
sum(iterable, start=0, /)Return the sum of a 'start' value (default: 0) plus an iterable of numbersWhen the iterable is empty, return the start value.This function is intended specifically for use with numeric values and mayreject non-numeric types.
看到形参列表中有一个 /,它表示 / 前的参数只能是位置参数,不能是关键字参数。
因此,以下调用是合法的:
a = [1,3,2,1,4,2]sum(a,2) # start=2 表示求和的初始值为 215
以下调用是非法的,iterable 参数不能被赋值为关键字实参:
sum(iterable=a,start=2)TypeError: sum() takes no keyword arguments
以后再查看Python中函数用法时,应该可以看懂了吧。
10.5 偏函数functools.partial
Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。
先来看下Python官方的描述:
# content of _functools.pyclass partial(object):"""partial(func, *args, **keywords) - new function with partial applicationof the given arguments and keywords."""pass
翻译过来就是,functools.partial可以给一个函数设置位置参数和关键字参数的默认值,并且返回一个新的可调用对象。之后调用这个新的可调用对象时,就自动带上了functools.partial设置的默认参数值,从而可以传递更少的参数。举个例子:
from functools import partialdef add(a, b, *arg, **kwargs):return a + b, arg, kwargsadd10 = partial(add, 10, kw1=1) # 设置add函数的位置参数a的默认值为10,关键词参数kwargs中的参数kw1的默认值是1,并返回新的可调用对象add10print(add10(11, 12)) # 调用新的函数对象add10,只需要在传递add函数的变量b的值就可以了
用Pycharm调试上面的代码,在add函数的return语句处添加断点,可以看到add10这个对象中args属性里面有一个10,kwwargs里面有一个"kw"=1,这就是通过partial偏函数设置进去的。
当调用add10时,只需要提供变量b=11和arg的值12,add10就能够将其与偏函数设置的值一起传递给原函数add了。
本文分享自微信公众号 - 明说软件测试(liuchunmingnet)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

