“ 函数是 Python 程序中不可或缺的一部分,它是的程序模块化、清晰化。Python的不少功能都是经过内置函数提供的,好比 sorted() 表示对一个集合序列排序,len() 表示返回一个集合序列的长度大小等等。这节课,咱们主要来学习 Python 的自定义函数。”
javascript
10.1 定义函数
使用def关键字php
函数能够有返回值也能够没有返回值css
# content of test_sample.pydef inc(x): # 有返回值 return x + 1
def test_answer(): # 没有返回值 assert inc(3) == 5
10.2 调用函数
add_one=inc(3)java
函数被调用时,这个函数此前必须定义过python
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。sql
10.3.2 默认值参数
def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True): pass
这是Python内置的打开文件的函数,调用open打开文件时,能够只传递file文件路径,其余的参数能够不传递实参值,由于其余的参数都具备默认值。mode是打开文件的模式,默认值是r,表示以读的方式打开文件,默认值参数必须指向不可变对象。swift
不要这样:数组
def add_end(li=[]): pass
要这样:
ruby
def add_end(li=None): pass
10.3.3 变长参数
能够给函数一次性传递多个参数,或者传递一个列表或元组。定义函数时在参数名前加一个星号*。bash
def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n return 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]) -> value max(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its biggest item. The default keyword-only argument specifies an object to return if the 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 the reverse 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]) -> value min(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its smallest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the smallest argument. """ pass
min 函数的源码文档中,举了两个例子,其中的形参有 *
符号,又有 []
?他们都表示啥意思呢?
函数形参列表中符号 *
表示,后面的形参只能为关键字参数,不能为位置参数,[]里面的参数是可选的,不是必填的,例如传递一个key参数和default参数时,必须写明参数名:
1,2,3,4,2,2,3,4] > a = [x: a.count(x), default=1) # 求出个数最少的元素 > min(a,key=lambda 1
由于default是可选的,所以还能够这样:
1,2,5,9,4,6,3] > list=[x:-x) # 取反后最小的值 > min(list,key=lambda 9
再来看一个min函数的用法,求一段文本中出现次数最少的字母。
import string
def 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): pass
func(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 numbers
When the iterable is empty, return the start value. This function is intended specifically for use with numeric values and may reject 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 application of the given arguments and keywords. """ pass
翻译过来就是,functools.partial能够给一个函数设置位置参数和关键字参数的默认值,而且返回一个新的可调用对象。以后调用这个新的可调用对象时,就自动带上了functools.partial设置的默认参数值,从而能够传递更少的参数。举个例子:
from functools import partial
def add(a, b, *arg, **kwargs): return a + b, arg, kwargs
add10 = 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源创计划”,欢迎正在阅读的你也加入,一块儿分享。