Python 函数

Python 函数

函数的简单定义

def fib(n): # write Fibonacci series up to n """Print a Fibonacci series up to n.""" a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print() # Now call the function we just defined: fib(2000)

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

定义 函数使用关键字 def,后跟函数名与括号内的形参列表。函数语句从下一行开始,并且必须缩进。

函数内的第一条语句是字符串时,该字符串就是文档字符串,也称为 docstring,详见 文档字符串。利用文档字符串可以自动生成在线文档或打印版文档,还可以让开发者在浏览代码时直接查阅文档;Python 开发者最好养成在代码中加入文档字符串的好习惯。

函数在 执行 时使用函数局部变量符号表,所有函数变量赋值都存在局部符号表中;引用变量时,首先,在局部符号表里查找变量,然后,是外层函数局部符号表,再是全局符号表,最后是内置名称符号表。因此,尽管可以引用全局变量和外层函数的变量,但最好不要在函数内直接赋值(除非是 global 语句定义的全局变量,或 nonlocal 语句定义的外层函数变量)。

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用 按值调用 来传递的(其中的 值 始终是对象的 引用 而不是对象的值)。 1 当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。

函数定义在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问访该函数:

fib f = fib f(100)

0 1 1 2 3 5 8 13 21 34 55 89

fib 不返回值,因此,其他语言不把它当作函数,而是当作过程。事实上,没有 return 语句的函数也返回值,只不过这个值比较是 None (是一个内置名称)。一般来说,解释器不会输出单独的返回值 None ,如需查看该值,可以使用 print():

fib(0) print(fib(0))

None

编写不直接输出斐波那契数列运算结果,而是返回运算结果列表的函数也非常简单:

def fib2(n): # return Fibonacci series up to n """Return a list containing the Fibonacci series up to n.""" result = [] a, b = 0, 1 while a < n: result.append(a) # see below a, b = b, a+b return result f100 = fib2(100) # call it f100 # write the result

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

本例也新引入了一些 Python 功能:

return 语句返回函数的值。return 语句不带表达式参数时,返回 None。函数执行完毕退出也返回 None。

result.append(a) 语句调用了列表对象 result 的 方法 。方法是“从属于”对象的函数,命名为 obj.methodname,obj 是对象(也可以是表达式),methodname 是对象类型定义的方法名。不同类型定义不同的方法,不同类型的方法名可以相同,且不会引起歧义。(用 类 可以自定义对象类型和方法,详见 类 )示例中的方法 append() 是为列表对象定义的,用于在列表末尾添加新元素。本例中,该方法相当于 result = result + [a] ,但更有效。

函数传参详解

Python 传参的方式有多种,比如:位置参数、关键字参数、默认参数、特殊参数、关键字和位置参数、特殊参数和任意参数 下面我们来一一进行简单的看看各种传参的方式!

位置参数

位置参数,就是直接通过函数调用时,传递的参数。

def say_what(one:str,two:str): # 这里用了函数的注解,表明参数的类型,后面会讲到 print("one:"+one) print("two:"+two) say_what("位置参数1","position 2") # 直接通过第一个位置进行传参,

one:位置参数1 two:position 2

从上面的代码可以看到,直接可以通过相应的位置,就把参数传递给对应的变量,第一个位置就传给 one ,第二个位置就传给 two 如果顺序调换一下,那么结果就会不一样了:

say_what("position 2","position 1")

one:position 2 two:position 1

可以惨到 one 变量一直参与的是第一个传入的参数。这就是位置参数

关键字参数

同样是上面的例子,我们来试试关键字参数:

say_what(two="This is two",one="This is One")

one:This is One two:This is two

从上面的结果可以看到,虽然参数位置在第一个,但是参数的值通过关键字,精准的传给了 one 和 two 。

但是如果此时出现了位置参数和关键字参数同时存在,那么会发生什么,我们代码来试试。

say_what("test 1",two="This is Two")

one:test 1 two:This is Two

say_what(two="This is Two","This is One")

Cell In[11], line 1 say_what(two="This is Two","This is One") ^ SyntaxError: positional argument follows keyword argument

可以看到明显的报错,也就是位置参数一定要在关键字参数的后面。这也是很显然的,会出现传递参数的歧义

默认参数

函数定义的时候,定义了默认参数,那么使用的时候就不一定传递参数了。

def say_what_default(first : str ,second : str,third : str,four : str= "Hello World!"): print("first:"+first) print("second:"+second) print("third:"+third) print("four:"+four) say_what_default("first","second","third")

first:first second:second third:third four:Hello World!

从结果可以看出,虽然我没有传递第四个参数,但是打印出来的有默认的值,当传递了以后,默认的值会被覆盖

say_what_default("first","second","third","four")

first:first second:second third:third four:four

默认参数的定义必须在所有参数的后面,否则会报错 一些错误的使用示例:

say_what_default() # 缺少参数传递 say_what_default(first="first",second="second","third") # 位置参数需放到关键字参数前面 say_what_default("first",first="first",second="second",third="third") # first 参数重复传递参数 say_what_default(five="five") # 位置参数传递以及缺少参数

有两个特殊参数,一个是/,一个是 */ 这个参数前面的参数必须是位置参数 在 * 这个参数后面的必须是关键字参数 / 必须在 * 前面,否则报错 在这两个特殊参数之间可以是位置参数可以是关键字参数,但是不能是默认参数

def special_param(a,b,c,/,d,e,f,*,g,h,i): print("a : " + a) print("b : " + b) print("c : " + c) print("d : " + d) print("e : " + e) print("f : " + f) print("g : " + g) print("h : " + h) print("i : " + i) special_param('a','b','c','d','e','f',g='g',h='h',i='i') print('--------------------------------------') special_param('a','b','c','d',e='e',f='f',g='g',h='h',i='i')

a : a b : b c : c d : d e : e f : f g : g h : h i : i -------------------------------------- a : a b : b c : c d : d e : e f : f g : g h : h i : i

任意参数

在传递一些固定参数后面,还可以传递一些不固定的参数,可以传递任意个 *name 是一个可变参数,可以接收任意个参数,这些参数会被封装成一个元组,名字可以任意取,但是必须带 * ,否则会报错 **name 是一个关键字参数,可以接收任意个参数,这些参数会被封装成一个字典,名字可以任意取,但是必须带 ** ,否则会报错 *name 必须在 **name 的前面,因为通过位置参数传参 *name**name 之间可以有参数但必须是关键字传参 *name 前面的参数只能是位置参数 (如果有传参的话), 其实就是遵循一个根本宗旨:位置参数在关键字参数后面

def any_params(a,seq=' ; ',*args,seq1=' | ',**kwargs): print(a) print(seq) print(seq.join(args)) print(seq1.join(kwargs.values())) any_params('a',' : ','b','c',seq1=' ? ',acs='123',bcs='456',csc='789') print('-----------------') any_params('a',seq1=' ? ',acs='123',bcs='456',csc='789') print('--------------') any_params('a',seq='+',seq1=' ? ',acs='123',bcs='456',csc='789') #

a : b : c 123 ? 456 ? 789 ----------------- a ; 123 ? 456 ? 789 -------------- a + 123 ? 456 ? 789

函数注解

函数注解 是可选的用户自定义函数类型的元数据完整信息(详见 PEP 3107 和 PEP 484 )。

标注 以字典的形式存放在函数的 annotations 属性中,并且不会影响函数的任何其他部分。 形参标注的定义方式是在形参名后加冒号,后面跟一个表达式,该表达式会被求值为标注的值。 返回值标注的定义方式是加组合符号 ->,后面跟一个表达式,该标注位于形参列表和表示 def 语句结束的冒号之间。 下面的示例有一个必须的参数,一个可选的关键字参数以及返回值都带有相应的标注:

def f(ham: str, eggs: str = 'eggs') -> str: print("Annotations:", f.__annotations__) print("Arguments:", ham, eggs) return ham + ' and ' + eggs f('spam')

Annotations: {'ham': <class 'str'>, 'eggs': <class 'str'>, 'return': <class 'str'>} Arguments: spam eggs 'spam and eggs'


#python# #语言基础#

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
为
下载 APP