文章目录
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 当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。
函数定义在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问访该函数:
python
fib
f = fib
f(100)
0 1 1 2 3 5 8 13 21 34 55 89
fib 不返回值,因此,其他语言不把它当作函数,而是当作过程。事实上,没有 return 语句的函数也返回值,只不过这个值比较是 None (是一个内置名称)。一般来说,解释器不会输出单独的返回值 None ,如需查看该值,可以使用 print():
python
fib(0)
print(fib(0))
None
编写不直接输出斐波那契数列运算结果,而是返回运算结果列表的函数也非常简单:
python
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 传参的方式有多种,比如:位置参数、关键字参数、默认参数、特殊参数、关键字和位置参数、特殊参数和任意参数
下面我们来一一进行简单的看看各种传参的方式!
位置参数
位置参数,就是直接通过函数调用时,传递的参数。
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
如果顺序调换一下,那么结果就会不一样了:
python
say_what("position 2","position 1")
one:position 2
two:position 1
可以惨到 one 变量一直参与的是第一个传入的参数。这就是位置参数
关键字参数
同样是上面的例子,我们来试试关键字参数:
python
say_what(two="This is two",one="This is One")
one:This is One
two:This is two
从上面的结果可以看到,虽然参数位置在第一个,但是参数的值通过关键字,精准的传给了 one 和 two 。
但是如果此时出现了位置参数和关键字参数同时存在,那么会发生什么,我们代码来试试。
python
say_what("test 1",two="This is Two")
one:test 1
two:This is Two
python
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
可以看到明显的报错,也就是位置参数一定要在关键字参数的后面。这也是很显然的,会出现传递参数的歧义
默认参数
函数定义的时候,定义了默认参数,那么使用的时候就不一定传递参数了。
python
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!
从结果可以看出,虽然我没有传递第四个参数,但是打印出来的有默认的值,当传递了以后,默认的值会被覆盖
python
say_what_default("first","second","third","four")
first:first
second:second
third:third
four:four
默认参数的定义必须在所有参数的后面,否则会报错
一些错误的使用示例:
python
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") # 位置参数传递以及缺少参数
有两个特殊参数,一个是/
,一个是 *
在 /
这个参数前面的参数必须是位置参数
在 *
这个参数后面的必须是关键字参数
/
必须在 *
前面,否则报错
在这两个特殊参数之间可以是位置参数可以是关键字参数,但是不能是默认参数
python
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
前面的参数只能是位置参数 (如果有传参的话), 其实就是遵循一个根本宗旨:位置参数在关键字参数后面
python
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 语句结束的冒号之间。 下面的示例有一个必须的参数,一个可选的关键字参数以及返回值都带有相应的标注:
python
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'
大家好,我是xwhking,一名技术爱好者,目前正在全力学习 Java,前端也会一点,如果你有任何疑问请你评论,或者可以加我QQ(2837468248)说明来意!希望能够与你共同进步