函数特点:
- 完成某一个特定的功能
- 代码重用
- 保持一致性,易维护,可扩展性
一 函数定义
数学函数 | python 函数 | |
定义 | f(x)=2x+1 | def f(x): # 函数定义,f 为函数名,x 为(形)参数,多个参数逗号分隔。 result = 2*x+1 # 函数体(功能逻辑实现的代码) return result # 函数返回值,遇 return,函数立即结束,后续语句不执行。 # 若返回多个值(return 1,2,'a',[3,4]),则以元祖(打包)返回。 # 若无返回值(return 语句),函数则返回 None |
调用 | y=f(1), y=3 | y=f(1) # 1 为该函数的实参,多个实参数逗号分隔,实参与形参一一对应 |
二 参数(可变长与不可变长)
- 参数
- 形参:只有函数被调用时,才分配内存单元,且只能在函数内部有效,当函数结束时被释放。
- 实参:可以是常量、变量、表达式、函数等。
- 参数对应关系
- 位置参数(实参与形参在位置上一一对应的关系)
# 测试 位置参数
def y(a, b, c): # a = 1, b = 2, c = 3
return a, b, c
print(y(1, 2, 3)) # 1 对应 a, 2 对应 b,3 对应 c
# (1, 2, 3)
- 关键字参数(以关键字名称一一对应)
# 测试 关键字参数
def y(a, b, c): # a = 2, b = 1, c = 3
return a, b, c
print( y( b = 1, a = 2, c = 3 ) ) # 实参名与形参名一样(名字及数量)
# (2, 1, 3)
- 位置与关键字参数混合(以位置参数为主)
# 测试 位置与关键字参数混合
def y(a, b, c): # a = 2, b = 1, c = 3
return a, b, c
print( y( 1, 2, c = 3 ) ) # 关键字参数一定要在位置参数的右边,位置参数比关键字参数要高
# (1, 2, 3)
- 默认参数(形参定义)
def y(a, b = 0): # b = 0 为默认参数
return a, b
print( y(1) )
# (1, 0)
print( y(1,2) )
# (1, 2)
- 参数组(* 与 ** ),非固定(数量或位置)参数,为后期提供扩展性
- * 形参能接受多个参数(能自动展开具有迭代特性的数据类型,对标位置参数)
def y(a, *args): # *args 接收所有位置参数。
if len(args) != 0 :
print(args[0], type(args))
return a, args
print( y( 1,2,3,4,5 ) )
# 2 <class 'tuple'>
# (1, (2, 3, 4, 5))
print(y( 1,*['a','b','c'])) # *实参能自动展开具有迭代特性的数据类型(但不适合字典)
# a <class 'tuple'>
# (1, ('a', 'b', 'c'))
print(y( 1,['a','b','c'])) # 没有* ,则列表为一个整体元素
# ['a', 'b', 'c'] <class 'tuple'>
# (1, (['a', 'b', 'c'],))
print( y(1) )
# (1, ())
print( y( 1,'abc' ) )
# abc <class 'tuple'>
# (1, ('abc',))
print( y( 1,*'abc' ) )
# a <class 'tuple'>
# (1, ('a', 'b', 'c'))
- **形参接受关键字参数,**将实参字典转换为关键字参数(如:a=1,b=2)
def y(a, **kwargs): # **kwargs 接收关键字参数(变量 = 值)。
if len(kwargs) != 0 :
print(kwargs, type(kwargs))
return a, kwargs
print( y( 1,**{ 'b': 1, 'c' : 2 } ) )
# {'b': 1, 'c': 2} <class 'dict'>
# (1, {'b': 1, 'c': 2})
- 混合使用(*args 在 **kwargs左边。 * 对标位置参数,** 对标关键字参数)
def y(*args, **kwargs): # **kwargs 接收关键参数(变量 = 值)。
if len(kwargs) != 0 :
print(kwargs, type(kwargs))
return args, kwargs
print( y( 'a','b',c = 1, d = 2 ) )
# {'c': 1, 'd': 2} <class 'dict'>
# (('a', 'b'), {'c': 1, 'd': 2})
def y(name, *args, **kwargs):
if len(kwargs) != 0 :
print(kwargs, type(kwargs))
return name, args, kwargs
print( y( 'elsa', *['a','b'], **{ 'c':1,'d':2} ) )
# {'c': 1, 'd': 2} <class 'dict'>
# ('elsa', ('a', 'b'), {'c': 1, 'd': 2})
- 参数特点概括
参数 | 位置参数 | 关键字参数 | ||
形参定义 | 单个对象 例:def y(a,b) | 组形式 例:def y(*args) args 默认名,建议使用 | 单个赋值表达式 例:def y(a,b) | 组形式 例:def y(**kwargs) kwargs 默认名,建议使用 |
实参格式 | 单个对象 例:y(1,2) | 可迭代数据类型 多个对象 例:y(1,2,3) 例:y(*[1,2,3]) | 单个赋值表达式 例:y(a=1,b=2) | 字典数据类型 多个赋值表达式 例:y(a=1,b=2) 例:y( **{'a':1, 'b'=2 } ) |
位置排列 | 最左边(1) | 2 | 3 | 4 |
特点 | 实参与形参位置对应 | *实参,自动展开为位置参数 | 实参与形参不需位置对应 | **实参,自动展开为关键字参数 |
def y(name, *args, age, **kwargs):
return name, args,age, kwargs
print( y( 'elsa', *['a','b'], age=18, **{ 'c':1,'d':2} )[2] )
# 18
三 局部与全局变量
- 全局变量:在书写时,没有缩进的格式下即全局变量,作用于整个代码中。
- 若无全局定义,而调用该全局变量,则不会向内层(函数、子程序等)搜索。
- 局部变量:在函数(或子程序)中定义的变量即局部变量,只能在函数(子程序)内使用。
- 无声明局部变量,则向外部(逐层)搜索同名的全局变量。
- 该(全局)变量若是可变数据类型,可读取,且可对内部的元素进行操作。
- 该(全局)变量若是不可变数据类型,只能读取。
- 声明局部变量,函数内只使用局部变量(与外部的同名全局变量无关)。
name = ['elsa']
def change_name():
name.append('tony') # 函数定义到变量调用时,若无该变量,则向外部收搜该变量,无法对外部变量赋值,但对可变类型可以内部操作。
print('change the name:', name)
change_name()
# change the name: ['elsa', 'tony']
name = 'elsa'
def change_name():
name = 'tony' # 局部变量定义,只能作用在本函数内,不会影响外部同名的变量
print('change the name:', name) # 机制:调用变量时,函数先从内部,再到外部收搜。
change_name()
# change the name: tony
print(name) # 此处变量为 全局变量
# elsa
- global 关键字(将局部变量提升为全局)
name = 'elsa'
def change_name():
global name # 将 name 提升为全局变量
name = 'tony' # 对全局变量重新赋值
print('change the name:', name)
change_name()
# change the name: tony
print(name) # 此处变量为 全局变量
# tony
name = 'elsa'
def change_name():
name = 'tony'
global name
print('change the name:', name) # 局部与global定义,只能允许存在其一
change_name()
print(name)
# 报错:SyntaxError: name 'name' is assigned to before global declaration
name = 'who'
def elsa_hello():
name = 'elsa'
def kate_hello():
global name
name = 'kate'
kate_hello()
print(name)
print(name) # who
elsa_hello() # elsa
print(name) # kate
- nonlocal 关键字(指定上一级变量)
name = 'who'
def elsa_hello():
name = 'elsa'
def kate_hello():
nonlocal name
name = 'kate'
kate_hello()
print(name)
print(name) # who
elsa_hello() # elsa
print(name) # who
四 函数的全局与局部
- 函数即变量
- 定义:函数定义与变量初始化(定义)一样(在内存开辟新空间存储相关数据)。
- 使用:函数使用与变量调用一样(通过内存地址访问执行)。
- 特点:函数具有变量的全局、局部的特性,及向外寻找函数定义。
def elsa():
print('elsa')
def kate(): # 该处定义,只能在 elsa()函数体内使用
print('kate')
kate()
elsa() # 正确输出
kate() # 报错:NameError: name 'kate' is not defined
# 该处的调用的是全局定义的 kate 函数
def elsa():
print('elsa')
hello = elsa
hello() # elsa
elsa() # elsa
def elsa():
print('kate')
hello() # elsa
elsa() # kate