再识 Python 函数

Author: ACatSmiling

Since: 2025-02-20

函数的基本使用

函数的简单定义:

def 函数名():
函数体

函数的调用:

函数名()

函数的参数

单个参数

# 定义,形参
def 函数名(参数名):
函数体
# 调用,实参
函数名(参数值)

多个参数

# 定义,形参以逗号分割
def 函数名(参数名1, 参数名2):
函数体
# 调用方式一,实参以逗号分割,实参与形参一一对应
函数名(参数值1, 参数值2)
# 调用方式二,指明形参对应的实参名称,此时,可以不必按照形参的顺序
函数名(参数名1=参数值1, 参数名2=参数值2)

不定长参数

# 方式一
# 定义,形参名前加一个 * 号表示不定长参数,在函数体中,可以直接以元组变量的方式使用该参数
def 函数名(*参数名):
函数体
# 调用,根据实际需求,传递对应的实参
函数名(参数值1, 参数值2, 参数值3, ...)
# 方式二
# 定义,形参名前加两个 ** 号表示不定长参数,在函数体中,可以直接以字典变量的方式使用该参数
def 函数名(**参数名):
函数体
# 调用,根据实际需求,传递对应的实参名称与实参
函数名(参数名1=参数值1, 参数名2=参数值2, 参数名3=参数值3, ...)

补充:装包和拆包。

缺省参数

# 定义,形参给予默认值,有默认值的形参,在调用时可以不用给定实参
def 函数名(参数名1=默认值1, 参数名2=默认值2):
函数体
# 调用,如果没给定参数值,会直接在函数体中使用默认值
函数名(参数值1, 参数值2)

参数传递机制

  • 值传递:函数接收的是变量的副本,在函数内部参数的改变,不会影响函数外部的变量。

  • 引用传递:函数接收的是变量的引用(内存地址),在函数内部参数的改变,会影响函数外部的变量。

  • 在 Python 中,是一种对象引用传递,也叫传值引用。如果数据类型是不可变类型(如整数、浮点数、字符串、元组等),传递的是对象的值的副本,在函数内部对参数的修改,不会影响函数外部的变量,此时,表现得像值传递;如果数据类型是可变类型(如列表、字典、集合等),传递的是对象的引用,在函数内部对参数的修改,会影响函数外部的变量,此时,表现得像引用传递。

    # 参数是不可变类型
    def change(num):
    print(id(num)) # 2034374541840
    print(num) # 10
    num = 666
    print(id(num)) # 2034374556880,修改方法中 num 的值后,num 发生了变化
    b = 10
    print(id(b)) # 2034374541840
    change(b)
    print((id(b))) # 2034374541840,修改方法中 num 的值后,方法外 b 的值没有改变
    print("----------------------")
    # 参数是可变类型
    def change(num):
    print(id(num)) # 2089520266368
    print(num) # [1, 2, 3]
    num.append(4)
    print(id(num)) # 2089520266368
    print(num) # [1, 2, 3, 4]
    b = [1, 2, 3]
    print(id(b)) # 2089520266368
    change(b)
    print((id(b))) # 2089520266368
    print(b) # [1, 2, 3, 4]

函数的返回值

def 函数名():
函数体
return 返回值

函数的使用描述

# 在函数体上面,添加三个双引号对注释
def 函数名():
"""
函数的说明信息
"""
函数体

通过help(函数名),可以查看函数的使用描述。一般情况下,函数的使用描述,需要包含以下信息:

  • 函数的功能。
  • 函数的参数含义、类型、默认值等。
  • 函数的返回值含义、类型等。

偏函数

偏函数:当编写一个参数比较多的函数时,如果有些参数,大部分场景下都是某一个固定值,那么为了简化使用,就可以创建一个新函数,指定需要使用的函数的某个参数为固定的值,这个新函数就叫偏函数。

定义:

def aaa(a, b, c, d):
print(a + b + c + d)
# 场景一:在该场景下,d 的值都是 1
# 定义偏函数 aaa1,默认 d 的值为 1,然后函数体中调用 aaa 函数
def aaa1(a, b, c, d=1):
aaa(a, b, c, d)
# aaa1(1, 2, 3) # 调用结果,控制台打印 7
# 场景二:在该场景下,d 的值都是 2
# 定义偏函数 aaa2,默认 d 的值为 2,然后函数体中调用 aaa 函数
def aaa2(a, b, c, d=2):
aaa(a, b, c, d)
# aaa2(1, 2, 3) # 调用结果,控制台打印 8
# Python 中,提供了 functools 模块的 partial 函数,能够快速的创建偏函数
import functools
# 参数 1 是需要创建偏函数的原函数,参数 2 是原函数中需要 "偏爱" 的参数名及其默认值
partial_function = functools.partial(aaa, d=3)
print(partial_function, type(
partial_function)) # functools.partial(<function aaa at 0x000001FF9ABA3D90>, d=3) <class 'functools.partial'>
# 调用定义的偏函数,在该场景下,d 的值都是 3
partial_function(1, 2, 3) # 调用结果,控制台打印 9

应用场景:

s = "11011"
# 使用 int(),可以将一个数值的字符串,转为 int 值,默认是以十进制转换
print(int(s)) # 11011
# 如果需要以二进制转换,则需要指定 base 参数
print(int(s, base=2)) # 27
# 假设有一个场景,都需要以二进制转换,则可以创建一个偏函数
import functools
partial_function = functools.partial(int, base=2)
print(partial_function(s)) # 27

高阶函数

高阶函数:当一个函数 A 的参数,接收的是另一个函数时,则把这个函数 A 称之为高阶函数。

应用场景一:

l = [{"name": "zhangsan", "age": 18}, {"name": "lisi", "age": 16}, {"name": "wangwu", "age": 20}, {"name": "maer", "age": 22}]
def get_key_name(p):
return p["name"]
def get_key_age(p):
return p["age"]
# sorted() 函数就是一个高阶函数,key 参数接收的是另一个函数
# 按照 name 排序,默认升序
result = sorted(l, key=get_key_name)
print(result) # [{'name': 'lisi', 'age': 16}, {'name': 'maer', 'age': 22}, {'name': 'wangwu', 'age': 20}, {'name': 'zhangsan', 'age': 18}]
# 按照 age 排序,默认升序
result = sorted(l, key=get_key_age)
print(result) # [{'name': 'lisi', 'age': 16}, {'name': 'zhangsan', 'age': 18}, {'name': 'wangwu', 'age': 20}, {'name': 'maer', 'age': 22}]

应用场景二:

# 定义一个高阶函数,动态计算两个数据
def calculate(num1, num2, calculate_function):
print(calculate_function(num1, num2))
# 加法运算
def addition_function(a, b):
return a + b
# 减法运算
def subtraction_function(a, b):
return a - b
# 乘法运算
def multiplication_function(a, b):
return a * b
# 除法运算
def division_function(a, b):
return a / b
# 调用
a = 10
b = 5
calculate(a, b, addition_function) # 15
calculate(a, b, subtraction_function) # 5
calculate(a, b, multiplication_function) # 50
calculate(a, b, division_function) # 2.0

返回函数

返回函数:是指一个函数内部,它返回的结果是另一个函数。

应用场景:

# 根据不同的参数,获取不同的操作
def get_function(flag):
# 加法运算
def addition_function(a, b):
return a + b
# 减法运算
def subtraction_function(a, b):
return a - b
# 乘法运算
def multiplication_function(a, b):
return a * b
# 除法运算
def division_function(a, b):
return a / b
# 根据 flag 的值,返回不同的操作函数
if flag == "+":
return addition_function
elif flag == "-":
return subtraction_function
elif flag == "*":
return multiplication_function
elif flag == "/":
return division_function
result_function = get_function("+")
print(result_function(1, 2)) # 3
result_function = get_function("*")
print(result_function(1, 2)) # 2

匿名函数

定义:

lambad 参数1, 参数2, ...: 表达式
  • 只能写一个表达式,不能直接 retrun。
  • 表达式的结果就是函数的返回值。
  • 只适用于一些简单的操作处理。

应用场景一:

# 方式一
# 首先,定义一个匿名函数
fun = lambda x, y: x + y
# 然后,调用匿名函数
result = fun(1, 2)
print(result) # 3
# 方式二
# 定义和调用匿名函数
result = (lambda x, y: x + y)(1, 2)
print(result) # 3

应用场景二:

# 简化高阶函数章节的示例,直接使用匿名函数,替换 get_key_name() 和 get_key_key()
l = [{"name": "zhangsan", "age": 18}, {"name": "lisi", "age": 16}, {"name": "wangwu", "age": 20}, {"name": "maer", "age": 22}]
# sorted() 函数就是一个高阶函数,key 参数接收的是另一个函数
# 按照 name 排序,默认升序
result = sorted(l, key=lambda p: p["name"])
print(result) # [{'name': 'lisi', 'age': 16}, {'name': 'maer', 'age': 22}, {'name': 'wangwu', 'age': 20}, {'name': 'zhangsan', 'age': 18}]
# 按照 age 排序,默认升序
result = sorted(l, key=lambda p: p["age"])
print(result) # [{'name': 'lisi', 'age': 16}, {'name': 'zhangsan', 'age': 18}, {'name': 'wangwu', 'age': 20}, {'name': 'maer', 'age': 22}]

闭包

闭包:在函数嵌套的前提下,内层函数引用了外层函数中的变量(包括外层函数的入参),外层函数又把内层函数当作返回值进行返回,这个内层函数与其所引用的外层函数中的变量(包括外层函数的入参),称为闭包。

示例:

# 内部函数引用外部函数中定义的变量
def outer():
num = 10
def inner():
return num
return inner
func = outer()
print(func(), type(func)) # 10 <class 'function'>
# # 内部函数引用外部函数的入参
def outer(num):
def inner():
return num
return inner
func = outer(10)
print(func(), type(func)) # 10 <class 'function'>

应用场景:外层函数根据不同的参数,生成不同功能的函数。

# 闭包应用场景:根据配置信息,生成不同的分割线函数
def line_config(content, length):
def line():
print("-" * (length // 2) + content + "-" * (length // 2))
return line
# 调用
line1 = line_config("闭包", 20)
line1() # ----------闭包----------
line1() # ----------闭包----------
line2 = line_config("abc", 30)
line2() # ---------------abc---------------
line2() # ---------------abc---------------
line3 = line_config("123", 40)
line3() # --------------------123--------------------
line3() # --------------------123--------------------

注意事项:

  • 闭包中,如果需要修改引用的外层函数变量,需要使用nonlocal 变量声明,否则当作是闭包中,新定义的变量。

    def aaa():
    num = 10
    def bbb():
    num = 666
    print(num)
    # 说明闭包内修改 num 值,不会影响外层函数中的变量
    print(num) # 10
    bbb() # 666
    print(num) # 10
    return bbb
    aaa()
    def aaa():
    num = 10
    def bbb():
    # 声明闭包中的 num,就是外部函数中的变量
    nonlocal num
    num = 666
    print(num)
    # 说明闭包内修改 num 值,不会影响外层函数中的变量
    print(num) # 10
    bbb() # 666
    print(num) # 666
    return bbb
    aaa()
  • 当闭包内,引用了一个后期会发生变化的变量时,一定要注意

    # 当函数被调用的时候,才会真正确定内部变量标识对应的值,在此之前,都是作为一个普通的变量标识存在
    # 在函数内部打印一个变量 a,但是 a 未定义
    def aaa():
    print(a)
    print("a") # 此时,程序并不会报错,因为没有调用 aaa()
    # aaa() # 此时,程序会报错,NameError: name 'a' is not defined
    # 根据上面分析的思路,当闭包内,引用了一个后期会发生变化的变量时,一定要注意变量的定义顺序
    def bbb():
    num = 10
    def ccc():
    print(num)
    num = 20
    return ccc
    func = bbb()
    func() # 最终结果,打印的 num 是 20,不是 10
    # 示例二
    def ddd():
    funcs = []
    for i in range(1, 4):
    def eee():
    print(i)
    funcs.append(eee)
    return funcs
    new_func = ddd()
    print(
    new_func) # [<function ddd.<locals>.eee at 0x000002062A833C70>, <function ddd.<locals>.eee at 0x000002062A833D00>, <function ddd.<locals>.eee at 0x000002062A833D90>]
    # 调用,打印的都是 3,虽然在循环中定义新的函数,但最终调用的时候,i 值是循环的最后一个赋值,也就是 3
    new_func[0]() # 3
    new_func[1]() # 3
    new_func[2]() # 3
    # 如果想打印 1,2,3,做如下改进
    def ddd():
    funcs = []
    for i in range(1, 4):
    def eee(num):
    def fff():
    print(num)
    return fff
    funcs.append(eee(i))
    return funcs
    new_func = ddd()
    print(
    new_func) # [<function ddd.<locals>.eee.<locals>.fff at 0x0000025C3C973EB0>, <function ddd.<locals>.eee.<locals>.fff at 0x0000025C3C973BE0>, <function ddd.<locals>.eee.<locals>.fff at 0x0000025C3C973F40>]
    new_func[0]() # 1
    new_func[1]() # 2
    new_func[2]() # 3

装饰器

装饰器:在函数名以及函数体不改变的情况下,给一个函数附加一些额外的代码。

定义:

# 定义装饰器
def check_login(func):
print("装饰器的执行时间,是立即执行") # 当代码运行时,即使没有调用函数,只要添加了装饰器的语法糖,就会打印这段话
def inner():
print("登陆验证")
func()
return inner
# 定义功能函数,并使用语法糖添加装饰器,语法糖的效果,等同于:fss = check_login(fss)
@check_login
def fss():
print("发说说")
# 调用功能函数
# fss()

进阶:

  • 多个装饰器叠加时,顺序是:从上到下装饰,从下到上执行。

    # 装饰器一
    def wrapper_line(func):
    def inner():
    print("-" * 30)
    func()
    return inner
    # 装饰器二
    def wrapper_start(func):
    def inner():
    print("*" * 30)
    func()
    return inner
    # 定义功能函数,添加两个装饰器,顺序是:从上到下装饰,从下到上执行。
    @wrapper_line
    @wrapper_start
    def aaa():
    print("aaa")
    # 调用功能函数
    aaa()
    ------------------------------
    ******************************
    aaa
  • 对有参数的函数进行装饰:使用元组和字典,接收被装饰函数的参数。

    # 装饰器
    def wrapper_line(func):
    # 不同的被装饰函数,入参可能不相同,使用元组和字典,接收被装饰函数的参数(会自动匹配哪些参数为元组,哪些参数为字典,拆包和装包)
    def inner(*args, **kwargs):
    print("-" * 30)
    print(args, kwargs)
    func(*args, **kwargs)
    return inner
    # 功能函数一,单个参数
    @wrapper_line
    def aaa(num):
    print(num)
    # 功能函数二,多个参数
    @wrapper_line
    def bbb(num1, num2, num3):
    print(num1, num2, num3)
    # 调用功能函数
    aaa(123)
    bbb(111, 222, num3="abc")
  • 对有返回值的函数进行装饰:在闭包中,将被装饰函数调用后的返回值也返回。

    # 装饰器
    def wrapper_line(func):
    # 不同的被装饰函数,入参可能不相同,使用元组和字典,接收被装饰函数的参数(会自动匹配哪些参数为元组,哪些参数为字典,拆包和装包)
    def inner(*args, **kwargs):
    print("-" * 30)
    # print(args, kwargs)
    return func(*args, **kwargs)
    return inner
    # 功能函数一,无返回值
    @wrapper_line
    def aaa(num):
    print(num)
    # 功能函数二,有返回值
    @wrapper_line
    def bbb(num1, num2, num3):
    print(num1, num2, num3)
    return num1 + num2 + num3
    # 调用功能函数
    result1 = aaa(123)
    result2 = bbb(111, 222, num3=666)
    # 打印功能函数调用的结果
    print("*" * 30)
    print(result1, result2) # None 999
  • 带有参数的装饰器:把 @ 符号后面的内容,整体作为装饰器,用来装饰被装饰的函数。

    # 外层:获取内部装饰器的装饰器,带有一个参数,根据不同的参数,获取不同的装饰器
    def get_wrapper(char):
    # 内层:根据外层装饰器入参,打印不同分割线的装饰器
    def wrapper_char(func):
    # 不同的被装饰函数,入参可能不相同,使用元组和字典,接收被装饰函数的参数(会自动匹配)
    def inner(*args, **kwargs):
    print(char * 30)
    # print(args, kwargs)
    return func(*args, **kwargs)
    return inner
    return wrapper_char
    # 功能函数一,打印 - 分割线
    @get_wrapper("-")
    def aaa(num):
    print(num)
    # 功能函数二,打印 * 分割线
    @get_wrapper("*")
    def bbb(num):
    print(num)
    # 调用
    aaa(666)
    bbb(666)

生成器

生成器:是一个特殊的迭代器,但是其抽象程度更高(反过来,迭代器不一定是生成器)。其拥有迭代器的特性:惰性计算数据,节省内存;能够记录状态,并通过 next() 函数,访问下一个状态;具备可迭代性。但是,如果想打造一个自己的迭代器,需要实现很多方法,比较复杂,而生成器则可以很方便的实现。

定义:

  • 生成器表达式:把列表推导式的 [] 修改成 ()。

    # 列表推导式
    l = [i for i in range(1, 100) if i % 2 == 0]
    print(
    l) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]
    # 弊端:如果是一个很大的列表,无法做到数据惰性生成,占用大量内存
    # 生成器表达式
    l = (i for i in range(1, 100) if i % 2 == 0)
    print(l, type(l)) # <generator object <genexpr> at 0x0000023D2A8B5BD0> <class 'generator'>
    # 生成器的调用---遍历,同迭代器(遍历的方式不会报错)
    for i in l:
    print(i)
  • 生成器函数:函数中包含 yield 语句,这个函数的执行结果就是生成器。

    # 生成器函数,包含 yield 语句,yield 语句,就是一个一个的状态
    # yield 语句可以阻断当前的函数执行,当使用 next() 或者 __next__() 时,都可以让函数继续执行,
    # 当执行遇到下一个 yield 语句时,又会被阻断
    def generator_function():
    yield 1
    print("a")
    yield 2
    print("b")
    yield 3
    print("c")
    yield 4
    print("d")
    # 生成一个生成器
    func = generator_function()
    print(func, type(func))
    # 调用生成器
    print(next(func)) # 在 yield 1 之前,没有输出,控制台输出 1,然后停止
    print(next(func)) # 在 yield 1 和 yield 2 之间,先输出 a,再输出 2,然后停止
    print(next(func)) # 在 yield 2 和 yield 3 之间,先输出 b,再输出 3,然后停止
    print(next(func)) # 在 yield 3 和 yield 4 之间,先输出 c,再输出 4,然后停止
    print(next(func)) # 在 yield 4 之后,先输出 d,后续没有 yield 语句,也就没有状态了,会报一个错误 StopIteration
    # 简化版
    def generator_function():
    for i in range(1, 9):
    print("num: ", i ** 2)
    yield i
    func = generator_function()
    print(func.__next__())
    print(func.__next__())

方法:

  • send() 方法send() 方法有一个参数,指定的是上一次被挂起的 yield 语句的返回值,相比于 next(),可以额外的给 yield 语句传值。

    # yield 语句,正常是无返回值的
    def generator_function():
    yield_1 = yield 1
    print(yield_1)
    yield_2 = yield 2
    print(yield_2)
    yield_3 = yield 3
    print(yield_3)
    yield_4 = yield 4
    print(yield_4)
    # 生成一个生成器
    func = generator_function()
    print(func, type(func))
    # 使用 next() 方法或者 __next()__ 方法调用生成器,yield 语句输出都是 None
    # print(next(func)) # 在 yield 1 之前,没有输出,控制台输出 1,然后停止
    # print(next(func)) # 在 yield 1 和 yield 2 之间,先输出 None,再输出 2,然后停止
    # print(next(func)) # 在 yield 2 和 yield 3 之间,先输出 None,再输出 3,然后停止
    # print(next(func)) # 在 yield 3 和 yield 4 之间,先输出 None,再输出 4,然后停止
    # print(next(func)) # 在 yield 4 之后,先输出 None,后续没有 yield 语句,也就没有状态了,会报一个错误 StopIteration
    # 使用 send() 方法调用生成器,给 send() 方法传参,可以成为 yield 语句的输出内容
    # 注意:第一次调用 send() 方法时,需要传递 None,否则报错:TypeError: can't send non-None value to a just-started generator
    # 因为 send() 方法的入参是上一个 yield 语句的输出,第一次调用,阻断时前面没有 yield 语句
    # print(func.send(None)) # 在 yield 1 之前,没有输出,控制台输出 1,然后停止
    # print(func.send("ooo")) # 在 yield 1 和 yield 2 之间,先输出 ooo,再输出 2,然后停止
    # print(func.send("ooo")) # 在 yield 2 和 yield 3 之间,先输出 ooo,再输出 3,然后停止
    # 或者先调用 next()/__next()__ 方法,再调用 send() 方法
    print(func.__next__()) # 在 yield 1 之前,没有输出,控制台输出 1,然后停止
    print(func.send("ooo")) # 在 yield 1 和 yield 2 之间,先输出 ooo,再输出 2,然后停止
    print(func.send("ooo")) # 在 yield 2 和 yield 3 之间,先输出 ooo,再输出 3,然后停止
  • close() 方法:关闭生成器。如果不想继续使用生成器了,可以使用 close() 方法关闭生成器,生成器关闭之后,无法再次被调用,否则会报错。

    def generator_function():
    yield 1
    print("a")
    yield 2
    print("b")
    yield 3
    print("c")
    yield 4
    print("d")
    # 生成一个生成器
    func = generator_function()
    print(func, type(func))
    # 调用生成器
    print(next(func))
    # 关闭生成器
    func.close()
    # 生成器关闭后,如果再次调用,会报错
    print(next(func)) # 报错:StopIteration

注意事项:

  • 生成器只能遍历一次,如果需要多次遍历,则需要再次生成。
  • 生成器执行时,如果碰到 return 语句,直接终止,抛出 StopIteration 异常。

递归函数

递归函数:函数 A 内部,继续调用函数 A。

示例:

# 求一个数字的阶乘
def func(num):
if num == 1:
return 1
return num * func(num - 1)
print(func(9)) # 362880

函数的作用域

变量的作用域:变量的作用范围,也即变量的可操作范围。Python 是静态作用域,在 Python 中,变量的作用域源于它在代码中定义的位置,在不同的位置,可能有不同的命名空间。

命名空间:是指作用域的体现形式。Python 中有多种命名空间,可以用 Python-LEGB 表示:

  • L:Local,函数内的命名空间。作用范围:当前整个函数体的范围。

  • E:Enclosing function locals,外部嵌套函数的命令空间。作用范围:闭包函数。

  • G:Global,全局命名空间。作用范围:当前模块(文件)。

  • B:Builtin,内建模块命名空间。作用范围:所有模块(文件)。

  • LEGB 规则:按照 L ---> E ---> G ---> B 的顺序查找变量。

  • 注意:Python 中没有块级作用域,块级作用域是指代码块中,if、while、for 后面的代码块。、

    if True:
    a = 10
    # if 块中定义的变量,在 if 块外面也可以使用
    print(a)

基于命名空间的常见变量类型:

  • 局部变量:在一个函数内部定义的变量,作用域为函数内部。使用 locals() 方法,可以查看所有的局部变量。

  • 全局变量:在函数外部,文件最外层定义的变量,作用域为整个文件内部。使用 globals() 方法,可以查看所有的局部变量。

  • 局部变量和全局变量的查看:

    # 全局变量
    num = 999
    def aaa():
    # 全局变量
    global num
    num = 10
    # 局部变量
    a = 1
    b = 2
    print(locals())
    aaa() # {'a': 1, 'b': 2}
    print(globals()) # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000029143EA48B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\Codes\\dify-0.15.3\\api\\test.py', '__cached__': None, 'num': 10, 'aaa': <function aaa at 0x0000029143DE3D90>}
  • 局部变量和全局变量之间的切换:

    # 全局变量
    num = 999
    def aaa():
    # 局部变量
    num = 10
    print(num)
    print(num) # 999
    aaa() # 10
    print(num) # 999
    # 全局变量
    num = 999
    def aaa():
    # 使用 global 将 num 变为全局变量
    global num
    num = 10
    print(num)
    print(num) # 999
    aaa() # 10
    print(num) # 10
  • 注意事项:

    • 访问原则:从内到外。
    • 变量定义时,尽量将全局变量放在最上面,命名前加 g_ 用于区分。
    • 如果出现全局变量和局部变量重名的情况,按就近原则获取,如果在函数中使用全局变量,需添加 global 关键字声明。

本文参考

https://www.bilibili.com/video/BV12b411g7G7

posted @   ACatSmiling  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示