python11:函数
当你需要编写大型程序时,你可能想要写一段代码供其它地方调用,或者将程序中的相同逻辑抽出来,这时你就需要用到函数。但函数不仅能提供这些功能,通过使用函数还能帮助我们更容易的理解代码。
定义函数
下面的代码定义了一个函数fib,用于计算Fibonacci数列:
>>> def fib(n): """Print a Fibonacci series up to n.""" a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() >>> fib(200) 0 1 1 2 3 5 8 13 21 34 55 89 144首先是关键词def,后面跟函数名和参数列表。从下一行开始就是函数的主体,必须缩进。
函数的第一行可以是描述性的字符串,可选,如果有,则会作为函数的一部分进行存储,成为文档字符串。有工具可以使用文档字符串自动生成在线或者打印的文档,也可以通过下面的方式访问:
>>> fib.__doc__ 'Print a Fibonacci series up to n.'或者使用help函数:
>>> help(fib) Help on function fib in module __main__: fib(n) Print a Fibonacci series up to n.函数可以使用return返回一个值,例如,为上面的fib函数返回一个结果序列:
>>> def fib2(n): """Return a list containing the Fibonacci series up to n.""" result = [] a, b = 0, 1 while a < n: result.append(a) a, b = b, a+b return result >>> f100 = fib2(100) >>> f100 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]如果函数没有return语句,则返回None,如:
>>> f100 = fib(100) 0 1 1 2 3 5 8 13 21 34 55 89 >>> print(f100) None下面介绍更多python中函数的更多特性。
为参数指定默认值
为函数参数指定默认值非常有用,这样在调用该函数时可以指定更少的参数,例如:
>>> def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while True: ok = input(prompt) if ok in ('y', 'ye', 'yes'): return True if ok in ('n', 'no', 'nop', 'nope'): return False retries = retries - 1 if retries < 0: raise OSError('uncooperative user') print(complaint)该函数你可以通过下面的方式调用:
1)仅指定强制参数:
>>> ask_ok('Do you really want to quit?') Do you really want to quit?y True2)给可选参数中的一个:
>>> ask_ok('OK to overwrite the file?', 2) OK to overwrite the file?n False3)给出所有参数:
>>> ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!') OK to overwrite the file?n False需要注意的是,函数的默认值在定义的一刻就确定了,例如:
>>> i = 5 >>> def f(arg=i): print(arg) >>> i = 6 >>> f() 5由于定义f的时候i的值为5,所以调用f()总是打印5。
警告:默认值只会赋值一次,但当默认值是一个可变对象时(例如list、字典、或者可变类的实例),将可能存在问题,看下面的例子,将传入的值累计在了一起:
>>> def f(a, L=[]): L.append(a) return L >>> print(f(1)) [1] >>> print(f(2)) [1, 2] >>> print(f(3)) [1, 2, 3]如果你不想在的多个调用间共享默认值,你可以这样做:
>>> def f(a, L=None): if L is None: L = [] L.append(a) return L
关键字参数
函数可以使用关键字参数来调用,形式为:kwarg=value。下面是一个例子:
>>> def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It's", state, "!")parrot指定了一个强制参数和3个可选参数。parrot可以使用下面的形式调用:
parrot(1000) parrot(voltage=1000) parrot(voltage=1000000, action='VOOOOOM') parrot(action='VOOOOOM', voltage=1000000) parrot('a million', 'bereft of life', 'jump') parrot('a thousand', state='pushing up the daisies')注意下面的调用方式是无效的:
parrot() parrot(voltage=5.0, 'dead') parrot(110, voltage=220) parrot(actor='John Cleese')
可变长度参数
函数支持可变长度参数,传入的参数将被打包为一个元组,在可变参数之前,0个或者多个参数可以提供。
>>> def write_multiple_items(file, separator, *args): file.write(separator.join(args))*args表示可以输入任意个参数。通常,可变参数都会放到参数列表的最后,因为他们将包括所有后面的输入参数。任何可变参数后面的参数都必须以关键字参数的形式使用。下面看一个具体的例子:
>>> def concat(*args, sep="/"): return sep.join(args) >>> concat("earth", "mars", "venus") 'earth/mars/venus' >>> concat("earth", "mars", "venus", sep=".") 'earth.mars.venus'除了‘*‘,python还支持‘**‘。‘**‘表示传入的参数为字典,看下面的例子:
>>> def print_params(**params): print(params) >>> print_params(x=1,y=2,z=3) {'z': 3, 'x': 1, 'y': 2}这样,打印出params为一个字典。下面看一个综合的例子:
>>> def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any", kind, "?") print("-- I'm sorry, we're all out of", kind) for arg in arguments: print(arg) print("-" * 40) keys = sorted(keywords.keys()) for kw in keys: print(kw, ":", keywords[kw]) >>> cheeseshop("Limburger", "It's very runny, sir.", "It's really very, VERY runny, sir.", shopkeeper="Michael Palin", client="John Cleese", sketch="Cheese Shop Sketch") -- Do you have any Limburger ? -- I'm sorry, we're all out of Limburger It's very runny, sir. It's really very, VERY runny, sir. ---------------------------------------- client : John Cleese shopkeeper : Michael Palin sketch : Cheese Shop Sketch
解包list和元组
前面已经使用‘*‘和‘**‘将传入参数打包为一个元组和字典,但如果参数已经为一个list或者元组,怎么将其作为参数传入函数呢?可以使用‘*‘和‘**‘来将其解包。看下面的例子:
>>> args = [3, 6] >>> list(range(*args)) [3, 4, 5]同样的方式,字典可以作为关键字参数使用,通过使用‘**‘操作符:
>>> def parrot(voltage, state='a stiff', action='voom'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.", end=' ') print("E's", state, "!") >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"} >>> parrot(**d) -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
Lambda表达式
使用lambda关键字可以创建小的匿名的函数,例如下面的函数返回两个参数的和:
lambda a, b: a+blambda函数在语法上被限制为单表达式,语义上,他们仅是通常的函数定义的简化语法。像嵌套函数定义,lambda函数引用包含范围内的变量。
>>> def make_incrementor(n): return lambda x: x + n >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43上面是使用Lambda表达式返回了一个函数,下面是另一个例子,传递一个小的函数作为参数:
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')] >>> pairs.sort(key=lambda pair: pair[1]) >>> pairs [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
函数注释
函数注释是可选的,包括关于用户定义函数的任意的信息。python本身和标准库都不使用函数注释,这里展示一下函数注释的语法。
注释被存储在函数的__annotations__属性中,参数注释通过参数后面加一个冒号定义,被一个表达式跟随;返回注释通过语法->定义。下面是一个例子:
>>> def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here": print("Annotations:", f.__annotations__) print("Arguments:", ham, eggs) >>> f('wonderful') Annotations: {'return': 'Nothing to see here', 'ham': 42, 'eggs': <class 'int'>} Arguments: wonderful spam
作用域
python中变量被放在一个字典中,通过“名称->值”的形式存储。内建的vars函数可以返回这个字典:
>>> x = 1 >>> scope = vars() >>> scope['x'] 1这种字典就叫做命名空间或者作用域。每个函数调用都会创建一个新的作用域,函数内的变量被称为局部变量,参数类似于局部变量。
python中提供了方法在函数中访问全局变量,可以使用globals函数获取全局变量值,该函数的近亲是vars,例如:
>>> def combine(parameter): print(parameter + globals()['parameter']) >>> parameter = 'berry' >>> combine('Shrub') Shrubberry也可以使用绑定全局变量的方法:
>>> x = 1 >>> def change_global(): global x x = x + 1 >>> change_global() >>> x 2但这样容易导致混乱,建议尽量不要这样做。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。