目录
认识函数:
当谈到Python编程语言中的函数时,指的是一段被定义的可重复使用的代码块。函数用于执行特定的任务,并且可以接受输入参数和返回输出结果。函数的使用可以帮助我们编写模块化、可重用和可维护的代码,是Python编程中非常重要的组成部分。
函数的格式如下:
def 函数名():
函数体
函数基础:
函数的调用:就是函数名(),写一个简单的函数:
def add(x,y):
return x + y
print(add(4,5))
以上函数的函数名就是add,需要用到该函数时就直接调用,方法就是add()。return后面时函数的返回值,需要打印返回值就使用print进行打印。
形参与实参:就是使用该函数时需要针对不同分情况都能够通用所需要传入的变量。
形参:就上面的函数add来说,add(x,y)里面的x和y就是形参。形参可以使用任何字母代替,格式和定义变量的格式差不多。
实参: 就上面的函数add来说,print(add(4,5))里面的4和5就是实参,实实在在的数据,当调用这个函数时,定义时有形参,调用的时候也一定要有实参。
位置参数,关键字参数,默认参数,可变元组参数,可变字典参数:
先看实例代码:
def fun(x,y=0,*arg,**args):
print(x,y,arg,args)
fun(y=5,x=6,"dg","srg",a=1,b=2)
首先,函数fun没有返回值,可以直接使用函数名()直接调用。
位置参数:在定义函数时函数名后面括号中,位置参数顾名思义和位置有很大谷关系,就是形参的位置和对应的实参的位置一定要一致,否则结果就是错的。函数fun中的x就是位置参数。
关键字参数:只出现在调用函数中,函数中有位置参数,不用关键字参数发的前提就是实参位置要和形参位置一致,否则就用关键字参数,就不用再考虑位置的情况。函数fun中的y=5,x=6,x和y就是关键字参数。
默认参数:默认参数就是参数有默认值,函数中只有实参和形参,肯定不会是实参,以上函数中y=0中的y就是默认参数,默认参数必须放在位置参数后面。
可变元组参数:就是一个形参名可以接受多个数据,接受后存入元组,固定格式就是*变量名,通常使用*args。可变元组参数必须放在位置参数和默认参数后面。
可变字典参数:就是一个形参名可以接受多个数据,接受后存入字典,固定格式就是**变量名,通常使用**args。可变元组参数必须放在位置参数和默认参数以及可变元组参数后面。调用时不要出现关键字参数。
函数进阶:
递归:
当一个函数在其函数体内调用自身的过程称为递归。递归函数能够解决一些需要重复执行相同操作的问题,通常会在函数内部包含一个停止递归的条件(base case)和一个递归调用。
下面是一个简单的例子,演示了如何使用递归计算阶乘:
def factorial(n):
# 定义停止递归的条件
if n == 0 or n == 1:
return 1
# 递归调用
return n * factorial(n-1)
# 调用函数
result = factorial(5)
print(result)
在上述代码中,factorial
函数计算一个数的阶乘。当输入的参数为 0 或 1 时,函数会直接返回结果 1,否则函数会通过调用自身来计算 n 的阶乘。这样,函数会依次调用自身,并不断减小输入的规模,直到满足停止条件。
需要注意的是,在使用递归时要确保递归调用可终止,即必须存在停止递归的条件。否则,递归函数会进入无限循环,导致程序崩溃。
此外,递归虽然能够解决一些问题,但有时它的性能会比较低。因为递归函数会反复调用自身,导致函数的堆栈帧不断增加,可能会消耗大量的内存。在使用递归时,需要谨慎考虑输入的规模,避免出现运行时间过长或内存溢出的问题。
变量的作用域
在 Python 中,函数的变量作用域指的是变量的可访问范围。变量的作用域决定了在程序中的哪些位置可以访问该变量以及该变量的生命周期。Python 中常见的变量作用域有全局作用域和局部作用域。
全局作用域(Global scope):
- 全局作用域中定义的变量可以在程序的任何位置被访问。
- 在函数外部定义的变量通常属于全局作用域。
- 全局作用域的变量可以使用
global
关键字进行声明,来指示在函数内部修改全局变量的值。
# 全局作用域
global_var = 10
def func():
# 访问全局变量
print(global_var)
# 修改全局变量
global global_var
global_var = 20
func() # 输出: 10
print(global_var) # 输出: 20
局部作用域(Local scope):
- 局部作用域指的是在函数内部定义的变量,只能在该函数内部访问。
- 在函数内部可以访问外部作用域的变量,但不能修改其值,除非使用
nonlocal
关键字。
def func():
# 局部作用域
local_var = 5
print(local_var)
# 访问外部作用域的变量
outer_var = 10
print(outer_var)
func() # 输出: 5, 10
# print(local_var) # 错误: NameError: name 'local_var' is not defined
闭包
闭包(Closure)是指一个函数对象能够访问并操作其自身范围外的变量。换句话说,闭包是一种函数及其相关环境(外部作用域)的组合体。
在 Python 中,当一个函数内部定义的函数引用了该函数的局部变量时,就创建了一个闭包。闭包在函数内部捕获并保存了自由变量(自由变量是指在函数的局部作用域之外定义,但在函数内部被使用的变量)的状态。
下面是一个示例来详细解释闭包:
def outer_func(x):
def inner_func(y):
return x + y
return inner_func
add_five = outer_func(5)
print(add_five(3)) # 输出: 8
在上述代码中,outer_func
是一个外部函数,它接受一个参数 x
,并定义了一个内部函数 inner_func
。内部函数引用了外部函数的局部变量 x
,并返回了一个对 x
进行加法操作的函数。当我们调用 outer_func(5)
时,它返回的是一个闭包 inner_func
,其中 x
的值被设置为 5。之后,我们可以像调用普通函数一样调用 add_five
,也就是调用闭包中的 inner_func
,传入参数 3,最终的结果是 8。
闭包的优点是它可以将状态(外部变量)捕获并保存起来,使得函数能够"记住"在创建它时存在的环境。这在某些场景下非常有用,例如创建工厂函数、实现装饰器等。
需要注意的是,闭包中的自由变量是保存在内部函数的 __closure__
属性中的元组中的 cell 对象。可以通过 __closure__
属性来访问和修改闭包中的自由变量。但需要注意的是,自由变量是只读的,无法直接修改。如果需要修改自由变量,可以使用 nonlocal
关键字。
总结起来,闭包是函数及其相关的外部环境的组合体,允许使用外部函数的状态来创建和访问内部函数。闭包提供了一种在函数之间共享状态的方式,充分利用了 Python 中的函数式编程特性。
装饰器
函数装饰器(Function Decorator)是 Python 语言中一种特殊的语法,用于修改或增强现有函数的行为。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数或可调用对象,通常用于在函数调用之前或之后执行一些额外的操作。
装饰器可以用于许多场景,例如日志记录、性能分析、输入验证、权限检查等。
下面是一个示例来详细解释装饰器的使用:
def decorator_func(original_func):
def wrapper_func(*args, **kwargs):
# 在函数调用之前执行一些操作
print("装饰器:在函数调用之前执行一些操作")
# 调用原始函数
result = original_func(*args, **kwargs)
# 在函数调用之后执行一些操作
print("装饰器:在函数调用之后执行一些操作")
return result
return wrapper_func
@decorator_func
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 调用装饰后的函数
在上述代码中,decorator_func
是一个装饰器函数,它接受一个函数 original_func
作为参数,并返回一个新的函数 wrapper_func
。wrapper_func
在调用原始函数之前和之后分别执行一些额外的操作。装饰器函数的内部函数 wrapper_func
使用了可变参数 *args
和 **kwargs
,以便能够接受任意数量的位置参数和关键字参数。
通过在函数定义之前加上 @decorator_func
,我们将 greet
函数装饰上了 decorator_func
。这等价于执行了语句 greet = decorator_func(greet)
,即用返回的 wrapper_func
函数替换了原始的 greet
函数。因此,当我们调用 greet("Alice")
时,实际上是调用了装饰后的 wrapper_func
,从而实现了在函数调用前后执行额外操作的效果。
需要注意的是装饰器可以通过 @decorator_func
的语法糖形式使用,也可以使用普通函数调用的形式手动应用装饰器。
装饰器是 Python 中非常有用和常见的特性,它能够优雅地改变函数的行为,使代码更加可维护和灵活。在实际开发中,经常会使用现有的装饰器或自定义装饰器来简化代码和增强函数的功能。