Python 函数

文章目录

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)说明来意!希望能够与你共同进步

相关推荐
通信仿真实验室18 分钟前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&21 分钟前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
belldeep1 小时前
python:reportlab 将多个图片合并成一个PDF文件
python·pdf·reportlab
吾爱星辰4 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer4 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
FreakStudio4 小时前
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
python·单片机·嵌入式·面向对象·电子diy
IT良4 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
丶21364 小时前
【CUDA】【PyTorch】安装 PyTorch 与 CUDA 11.7 的详细步骤
人工智能·pytorch·python
Kalika0-05 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j