1.函数目的
目的: 封装一定的功能,比如系统print就封装了打印函数;
减少重复代码的编写;提升代码的复用;提高代码的可读性;参数传递和返回值;分解复杂任务;
2.函数定义(声明)
定义:def 函数名(): pass 又叫方法。
3.函数调用
调用:函数名(),执行一个函数方法。
# 函数方法
# 定义 def 函数名():pass
def name():
print("kong")
# 函数调用
# 调用 函数名()
name()
4.函数形参
形参:形式参数,在函数定义时出现在()中的变量,形参是一个变量,需要使用实参赋值。
5.函数实参
实参:实际参数,在函数调用时出现在()中的数值。
# 形参 形式参数 是一个变量 需要使用实参赋值
# 在函数定义时出现在()中
def sister(num):
for i in range(num):
print("ying")
# 实参 实际参数
# 在函数调用时出现在()中
sister(5)
print("------------")
sister(2)
6.函数返回值
函数返回值:函数的执行结果。如果没有写return,返回None;return 可以返回多个数据,会将多个数据放入元组返回;return代表函数执行结束 后续代码不在执行;函数一旦返回后续代码不在执行 return 在函数内部可以终止无数层循环。
s = "输入数字"
s = input(s)
num = int(s)
print(num)
# 函数的返回值
# 执行print 返回None 如果函数没有return 默认返回None
print("hello")
# 执行max 返回数字
r = max(1, 2)
print(r)
def my_print():
print("haha")
# my_print 内部没有return 默认返回None
my_print()
def my_max(a, b):
# return 代表函数功能执行结束 后续代码不再执行
return 1, 2, 3, a + b
# 变量r用于接受函数计算结果
r = my_max(1, 2)
print(r)
7.函数的参数类型
位置参数(Positional Arguments):按照参数的位置顺序传递给函数,可以有任意多个位置参数。
关键字参数(Keyword Arguments):通过参数名来传递给函数,可以有任意多个关键字参数。
默认参数(Default Arguments):给参数指定默认值,在调用函数时如果没有传递对应参数,则使用默认值。
可变参数(Variable Arguments):接收任意数量的位置参数,可以使用*来定义。
关键字可变参数(Keyword Variable Arguments):接收任意数量的关键字参数,可以使用**来定义。
def my_fun(n, *args, info="hh", tips="xfmm", msg="xx", **kwargs):
"""
:param tips: 关键字参数
:param n:位置参数 按位置赋值
:param args:可变元组参数
:param info:关键字参数
:param msg:关键字参数
:param kwargs:字典参数
:return:
"""
for name in args:
print(f"{n}{name}{args}{info}{msg}{tips}{kwargs}")
my_fun(1, "xk", "xx", msg="xhkl", info="jh", more1="ldjh", more2="yqjh")
8.变量的作用域(global与nonlocal)
变量的作用域描述了变量在程序中可见的范围。在Python中,有三种作用域:局部作用域、全局作用域和非局部作用域。
局部作用域:在函数或代码块内部定义的变量具有局部作用域,它们只能在函数或代码块内部访问。当函数或代码块执行结束后,局部变量的作用域也随之结束。
全局作用域:在函数外部定义的变量具有全局作用域,它们可以在整个程序中的任何位置被访问。全局变量在程序执行期间一直存在,直到程序结束。
非局部作用域:在嵌套函数中定义的变量具有非局部作用域。这意味着它们既不是全局变量,也不是局部变量。如果一个嵌套函数中的变量既不是局部变量,也不是全局变量,但它在外部函数中定义,那么它就具有非局部作用域。
global关键字用于在函数内部声明一个全局变量。当在函数内部使用global关键字声明一个变量时,该变量会成为全局变量,可以在函数内外被访问和修改。
nonlocal关键字用于在嵌套函数内部声明一个非局部变量。当在嵌套函数内部使用nonlocal关键字声明一个变量时,该变量会被认为是非局部变量,可以在嵌套函数内部以及外部函数内部被访问和修改。
a = 1
print(a)
def my_fun():
# b 为函数内部变量 执行完函数 b回收 不能再使用b
b = 3
print(b)
# 函数内部想要使用修改全局变量需要使用关键字global
# global 表明在函数内部使用的a就是全局变量a
global a
print(a)
a = 2
my_fun()
print(a)
datas = [1, 2, 3]
def my_list():
global datas
print(datas)
datas = [4, 5, 6]
my_list()
print(datas)
def my_fun1():
i = 10
print("myfun1", i)
def my_fun2():
j = 2
# nonlocal声明非本地变量 但也不是全局变量
nonlocal i
i = 6
print("myfun2", i, j)
return my_fun2
r = my_fun1()
r()
9.匿名函数
函数名:指代函数内存地址,通过函数名找到函数。
匿名函数也被称为lambda函数。匿名函数是一种没有名称的函数,可以在任何需要函数对象的地方使用,通常用于一次性的简单函数。匿名函数可以作为其他函数的参数传递,也可以作为其他函数的返回值。
lambda关键字定义匿名函数的语法:lambda 参数列表: 表达式。
特点:只能包含单个表达式,不能包含多个语句或复杂的逻辑;返回值就是表达式的结果。
# 没有名字的函数 不能独立存在
# my_fun = lambda 形参列表:单行表达式
my_fun = lambda: print("xk")
print(type(my_fun))
my_fun()
my_fun = lambda msg: print(msg)
my_fun(417)
my_fun = lambda a, b: a if a < b else b
print(my_fun(10, 20))
my_fun = lambda name, age: print(f"{name}{age}")
my_fun("xk", "521")
my_fun = lambda x, y: x * y
print(my_fun(5, 6))
n = 10
f = lambda: print("xk")
f()
def my_fun(n, f):
for i in range(n):
f()
10.递归函数
递归函数是指在函数的定义中调用函数自身的过程。
递归函数必须包含至少一个基础情况,这是函数停止递归的条件。如果没有基础情况,函数会无限递归,最终导致堆栈溢出或程序崩溃。
在函数内部调用函数本身。这是递归函数的核心特征,通过递归调用,函数可以重复执行相同的操作,直到达到基础情况为止。
每次递归调用都会在内存堆栈上创建一个新的栈帧,因此递归深度受到堆栈大小限制的影响。在处理大量数据或者深度递归时,需要注意堆栈溢出的风险。
尽管递归是一种简洁的方法来解决问题,但它可能比迭代版本的函数更慢,因为每次调用都涉及函数调用和堆栈管理开销。在某些情况下,可以通过迭代方式实现相同的逻辑来提高性能。
递归函数的调试可能会比迭代函数更具挑战性,因为它涉及到多个函数调用的交织。在编写和调试递归函数时,建议使用打印语句或调试器来跟踪函数的执行路径。
# 递归函数:一种特殊的函数(自己调用自己)
# 要有递归出口
def main(v):
if v == 1:
return 1
else:
return v + main(v - 1)
print(main(3))
def get_sum(n):
if n == 1:
return 1
else:
return n * get_sum(n - 1)
print(get_sum(3))
def get_n(n):
if n == 1:
return 1
elif n == 2:
return 1
else:
return get_n(n - 1) + get_n(n - 2)
print(get_n(4))
递归函数是一种强大的编程技术,能够简化问题的解决方案,但在使用时需要小心处理递归调用的终止条件和效率问题。
11.闭包
闭包(Closure)是指函数对象可以访问其创建时所在的作用域(即定义时的作用域)中的变量,即使函数在其定义之后被传递到其他作用域或返回。
在编程语言中,每个函数都会创建一个作用域,其中包含函数的局部变量、参数以及它可以访问的外部变量。当函数定义在另一个函数内部时,它可以访问外部函数的作用域,这种情况下,该函数称为内部函数。
当一个内部函数(即闭包)被定义在外部函数中,并且该内部函数引用了外部函数的变量时,就形成了闭包。闭包使得函数可以访问其创建时的环境,即使该函数在创建后被传递到其他地方执行,它仍然可以访问到其所需的变量。
import random
def fun1():
print("fun1")
datas = []
def fun2():
datas.append(random.randint(0, 100))
print("fun2", datas)
return fun2
r = fun1()
r()
r1 = fun1()
r1()
print(id(r), id(r1))
用途:
封装:闭包允许创建封装的函数,隐藏函数的实现细节。
保持状态:闭包可以用来维持函数调用之间的状态,而不需要全局变量。
函数工厂:可以使用闭包创建函数工厂,动态生成函数。
闭包是一种强大的编程工具,它允许函数保持其创建时的环境状态,并能够在不同的上下文中被调用和使用。
12.装饰器
装饰器(Decorator)是Python中一种强大且灵活的语法,用于动态修改函数或类的功能。装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数(通常是对传入函数的增强或包装)。
定义装饰器:装饰器本身是一个函数,
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
# 在调用原始函数之前的操作
result = original_function(*args, **kwargs)
# 在调用原始函数之后的操作
return result
return wrapper_function
应用装饰器:使用装饰器可以通过在函数定义前使用 @
符号加上装饰器函数名的方式,将装饰器应用到目标函数上。
@decorator_function
def my_function():
print("Hello, world!")
# 调用被装饰后的函数
my_function()
特性及用途:
动态增强函数功能:装饰器允许你在不修改原始函数代码的情况下,为函数添加新的行为或功能,比如日志记录、性能测试、权限检查等。
多个装饰器的叠加:Python支持将多个装饰器叠加在同一个函数上,按照从上到下的顺序依次应用。
参数化装饰器:可以创建接受参数的装饰器,这样可以根据传入的参数动态调整装饰器的行为。
装饰器是Python中强大且常用的编程技术,可以显著提高代码的复用性和可维护性,特别是在需要为现有函数添加新功能而不改变其结构的情况下非常实用。