函数是什么?

函数是由一些组织好的,可重复使用的,用于实现某一特定功能的代码块。

函数的出现是为了使编程时代码更为简洁,提高程序的可读性、应用性等。

函数分为系统内建函数和用户自定义函数,如 print() 就是系统内建函数。

函数定义格式

自定义一个函数用于实现自己想要的功能,基本语法如下:

def functionname(parameters):
    "函数_说明字符串"
    function_suite
    return [expression]

函数以 def 关键词开头,接着是函数名称和圆括号(),再接着是一个冒号 : ,这样就完成了一个函数的简单声明。紧接着下方就是函数体,是函数真正要封装(执行)的内容,函数体内的代码必须使用相同的缩进(一般是4空格)。

  • functionname:为函数名称,由用户自定义,但不应与已有函数重名。
  • parameters:为传递参数,这里称为“形式参数”,当需要传入参数到函数内部时通多这里进行定义,数量不限;没有参数传递时可省略不用。
  • function_suite:为要实现功能的代码块,各代码块将要遵循缩进原则!
  • return:为返回语句,用于返回一个或多个参数,该语句为可选语句。
  • expression:为要返回的参数,它可以是任意类型,当缺省时默认返回 None

Python 函数没有结束符一说,它是通过代码缩进关系来确定函数关系的,一般在函数定义结束后会腾出一行空行。

无参数函数定义

实例:

def display():
    print("hello world")

函数调用

当我们定义好一个函数体后,我们就可以通过其函数名称进行调用,具体如下:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
def display():
    print("hello world")

display()  # 调用函数

运行输出:
hello world

带参数函数定义

定义带参数函数体时,可以在括号内声明一个或多个的传入参数(称为“形式参数”),参数之间用逗号 , 隔开;而在调用函数时同样需要传入相应个数的参数(称为“实际参数”),用于将形式参数替换为实际的值,传入的实际参数之间同样用逗号 , 隔开。

实例如下:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

def display ( str ):   # 定义一个传入参数str
    print("传入参数:", str)

display("这是一个自定义函数")     # 调用函数

运行输出:
传入参数: 这是一个自定义函数

说明:实例用在调用函数时,用实际的参数 “这是一个自定义函数” 替换 形式参数“ str ”,最后传入函数内给 print() 输出显示。

函数参数

在定义带参数函数时,都需要传入相应的参数。

函数参数可以支持以下类型:关键字参数、默认参数、不定长参数...

必备参数

必备参数:是指在定义带参数函数时,在后面的函数调用中,用户必须传入参数,而且传入的参数必须与定义的形参个数一致,否则程序将报错。

实例如下:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

def personal_info( name ):
    print("name:", name)

personal_info("小明")   # 传入参数,程序正常执行
personal_info()   # 不传入参数,程序将报错,并终止执行

实例输出:

name: 小明
Traceback (most recent call last):
File "C:\Users\QinTaiW\Desktop\aaa.py", line 8, in
personal_info( ) # 不传入参数,程序将报错,并终止执行
TypeError: personal_info() missing 1 required positional argument: 'name'

可见程序在执行到第二次调用函数时,由于没有传入必须的参数,所以程序报错并停止往下执行了。

同样的,当传入的实际参数比定义时的形式参数要多时,程序同样会报错和终止。同学们可以去尝试一下。

关键字参数

定义带参数函数,在调用函数必须传入相应的参数,否则解析器会报错,程序执行中断。

调用函数时,使用关键字方式赋值时,实参与形参无顺序关系,只根据关键字进行对应赋值。

实例如下:

#! /usr/bin/python3
# -*- coding: utf-8 -*-

def personal_info( name, age ):
    print("name:", name, "age:",age)

# 按顺序赋值(与顺序有关)
personal_info("小明",25)
personal_info(25, "小明")

# 按关键字赋值(与顺序无关)
personal_info(name="小明", age=25)
personal_info(age=25, name="小明")

运行输出:

name: 小明 age: 25
name: 25 age: 小明
name: 小明 age: 25
name: 小明 age: 25

可见调用函数时,直接赋值方式:实参与形参之间的传递方式是按顺序依次进行赋值的;按关键字方式赋值:实参与形参之间无顺序关系,它们之间只根据各自之间的关键字进行对应赋值。

注:不管是使用顺序方式赋值,还是关键字方式赋值,传入的实参个数必须与函数中定义的形参个数一致,不然程序将报错。

默认参数

默认参数:是指用户在自定义函数时,已给形参绑定了一个参数,该称为默认参数。

默认参数特点:已绑定了默认参数的函数,在调用函数时,可缺省该参数的传入,如果缺省该参数,函数执行时,则使用默认值;当不缺省该参数时,后面传入的实际参数将替代默认参数。

注意:没有绑定默认值的参数,在调用函数时,必须传入对应的值。
#! /usr/bin/python3
# -*- coding: utf-8 -*-

def personal_info( name, age=20 ):  # 绑定默认值
    print("name:", name, "age:",age)

personal_info(name="小明")    # 缺省 age 参数
personal_info(name="小明", age=25)   # 刷新 age 的值

实例输出:

name: 小明 age: 20
name: 小明 age: 25

可见使用默认参数的函数,在缺省实参时,程序执行中并不会报错,而是使用了定义函数时的默认值。

不定长参数

不定长参数的出现是为了满足,在定义函数后,可能因某些情况,在后面使用中需要一些输入的实参比定义前的形参要多。换句话来说就是,函数能处理比当初声明时更多的参数,这些参数称为不定长参数,常见的是传入一个列表、元组、字典 等类型的数据。

不定长参数使用 * 星号 或 ** 双星号来声明:

  • 【* 号不定长参数】:用于接收参数为 列表、元组... 迭代数据,冗余的数据将被存入一个 元组 当中。
  • 号不定长参数】:用于接收参数为 字典型 数据,冗余的数据将被存入一个 字典** 当中。

【* 号不定长参数】

在定义形参时,在形参的前面添加一个 * 号,表示可接收不定长参数,多余的参数将被存入一个元组中。实例如下:

实例1:

#! /usr/bin/python3
# ! -*- coding: utf-8 -*-

def custom_print(*aa):
    print(type(aa))      # 查看 aa 当前的类型
    print(aa)    # 输出显示 aa

custom_print("Python", "hello", "world")

输出如下:


('Python', 'hello', 'world')

分析:可见多余的参数都被接收到新的元组当中。

实例2:
功能:定义不定长参数,并一次赋予多个值。

#! /usr/bin/python3
# ! -*- coding: utf-8 -*-

def student_info(name, sex, subject, *score):
    print("name:", name, "sex:", sex)
    print("subject:", subject, "score:", score)

# 调用函数
student_info("小明", "男", "语文", 80, 92, 85, 87, 79, 82, 72)

输出如下:

name: 小明 sex: 男
subject: 语文 score: (80, 92, 85, 87, 79, 82, 72)

分析:调用函数时,函数中的实参依次赋值给形参,后面多余的参数全部由不定长参数*score接收下来,数据为元组类型。

实例3:
功能:输入一个不定长参数,求不定长参数里面的最大值。

#! /usr/bin/python3
# -*- coding: utf-8 -*-

def student_info(name, sex, subject,*score):   # 定义不定长参数 score
    print("name:",name, "sex:",sex)
    print("subject:",subject ,"max_score_is:",max(score) )    # 打印score中的最大值

all_subject_score = [80, 92, 85, 87, 79, 82, 72]

student_info("小明","男","语文",*all_subject_score)    # 传入列表,元组类型的参数时需在参数前添加(星号 *)

实例输出:

name: 小明 sex: 男
subject: 语文 max_score_is: 92

分析:在传入不定长参数时,如果是列表、元组类型的参数,需要在调用中的实参前使用星号(*)声明,这时数据才会被程序拆分出来,否者程序会认为列表、元组为一个参数。
如果想测试的同学,可以将调用函数中实参前的星号(*)去掉,然后再执行,此时程序会输出不一样的结果。

【** 号不定长参数】

双星号 ** 不定长参数主要是用来接收字典(dic)类型的数据,多余的参数将被存入一个 字典(dis) 中。实例如下:

实例1:

#! /usr/bin/python3
# -*- coding : utf-8 -*-

def my_function(**aa):
    print(type(aa))    # 查看当前 aa 的数据类型
    print(aa)    # 打印 aa 的数据

my_function(a=1, b=2, c=3)

实例输出:


{'a': 1, 'b': 2, 'c': 3}

分析:可见多余的参数被接收到新的字典当中,其中以形参名作为键(key)值,以实参作为数据(value)。

实例2:

#! /usr/bin/python3
# -*- coding : utf-8 -*-

params = {'name':'justin', 'number':'123-4567', 'balance':1000}

def account(name,number,balance):  # 定义 ** 不定长参数
    print( {'name_is':name, 'number_is':number, 'balance_is':balance} )    # 通过键获取对应的值

# 调用函数
account(**params)

实例输出:

{'name_is': 'justin', 'number_is': '123-4567', 'balance_is': 1000}

分析:定义**不定长参数时,在函数调用中,函数会根据‘键名’读入相应的‘键值’,即函数的形参将由字典的‘键值’所代替。

注意:在函数内部调用形参的值时,务必在形参的前面加上 : 冒号,否则编译器报错。

return 语句

return 语句主要用于把函数中指定的参数带回到主程序中,当缺省 return 返回表达式时,程序默认返回 None 。

在执行中,当程序执行 return 语句时,程序直接携带参数返回上级程序中(即退出当前函数体)。

注意:同一条件下只允许出现一个return 语句。

基本格式:

 return a[,b,c...n]

实例如下:

实例1:

#! /usr/bin/python3
# -*- coding : utf-8 -*-

def custom_sum( a, b ):
    return( a + b )  # 返回 a + b 的值

# 调用函数并显示计算结果
print( custom_sum(1000, 24) )

输出结果:

1024

分析:当调用函数时,程序执行函数中的语句,执行到return语句时,return语句将携带 a + b 的运算结果返回到主程序中。

yield 语句

yield 语句同样可以携带参数返回a,但它不会立刻中断当前函数。

实例功能:

模仿 Python 内置函数 range() 函数的功能,代码如下:

#! /usr/bin/python3
# -*- coding : utf-8 -*-

def xrange( n ):  # 自定义一个函数
    x = 0
    while x != n:
        yield x     # 返回 x 的值
        x += 1

for n in xrange(5):   # 调用函数
    print (n)

实例输出:

0
1
2
3
4

分析:通过分析可以知道程序执行到 yield语句时,并没有退出当前函数,而是继续往下执行,直到最后才返回当时所记录到的值。

lambda 表达式

lanbda 可以理解为是一个小函数, 其函数主体是一个表达式, 而不是代码块。

语法格式:

lambda arg1 [,arg2,.....argn] : expression

参数声明:

  • arg1: 定义的变量( 变量间用 , 号间隔)
  • expression : 函数体(一般为表达式)
  • 返回值: 参数自动返回,无需return语句

实例如下:

#! /usr/bin/python3
#  -*- coding : utf-8 -*-

# 定义 lambda 函数
custom_sum = lambda num_1, num_2: num_1 + num_2;

# 调用sum函数
print(custom_sum(1000, 24))

实例输出:

1024

可见 lanbda 表达式会自定返回其值,而无需额外添加 return 语句。

变量作用域

变量的作用域将变量划分为:全局变量 和 局部变量 两种。

  • 全局变量:定义在函数以外的变量称为全局变量,该变量可以在程序的任何地方进行调用。
  • 局部变量:定义在函数内部的变量称为局部变量,该变量只允许程序在函数内部进行调用。

实例演示:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

total = 0;  # 这是一个全局变量

def custom_sum(num_1, num_2):
    total = num_1 + num_2;  # total在这里是局部变量.
    print("函数内-局部变量 : ", total)

# 调用sum函数
custom_sum(1000, 24);
print("函数外-全局变量 : ", total)

实例输出:

函数内-局部变量 : 1024
函数外-全局变量 : 0

以上是简单的 全局变量 和 局部变量 的使用演示,当局部变量需要扩展为全局变量时,可以使用 global 关键字声明,如:global nun1,但一般不建议这样使用。

【其它说明】

1、变量查找规则: 从内到外
2、Python 中全局变量以模块文件为界
3、使用 locals() 函数查看所有局部变量的名字和值

完整学习教程请访问Python3 入门教程——目录索引

最后修改:2022 年 06 月 09 日
如果觉得我的文章对你有用,请随意赞赏