吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 449|回复: 9
收起左侧

[学习记录] Python函数的核心知识点

[复制链接]
muyu726 发表于 2025-3-14 14:35

一、函数的核心知识点

1.函数的参数

a.分类

  • 位置参数

  • 默认参数

  • 可变参数

    • *args 允许函数接收任意数量的位置参数,但是以元组的形式传入

    • **kwargs允许函数接收任意数量的关键字参数,但是以字典的形式传入

b.参数类型的执行顺序

规则:位置(必选)参数→默认参数→*arg→命名关键字参数→**kwargs

# 错误案例: pycharm环境会自动识别除该错误
def func(a=1, b):    # 默认参数在必选参数之后
    pass   

# 正确案例:
def func(b, a=1):
    pass

c.默认参数的陷阱:可变对象

默认参数的值在函数定义时就被计算并存储,如果默认值是可变对象(如列表、字典),多次调用时会共享同一对象

# 案例:默认参数为list为例
def func(a,lst=[]): 
    lst.append(a)
    print(lst)
func(a) 
func(b)

# 输出结果
[1]
[1, 2]

假如你想默认参数是可变参数,又不想共享该对象,将target赋值为None。用 None 占位,并在函数内初始化:

# 案例:
def func(a, target=None): 
    if target is None:
        lst = []
    lst.append(a)
    print(lst)
func(a) 
func(b)

d.*args**kwargs 的误用

  • 定义函数时*args 收集多余的位置参数为元组,**kwargs 收集多余的关键字参数为字典。
  • 调用函数时* 解包序列为位置参数,** 解包字典为关键字参数。
# 错误案例 【参数数量与解包的数量不对应】

def func(a, b):
    pass

args = (1, 2, 3)
func(*args)   
# 抛出错误,func中传入的参数的数量是2两个,而*args解包后是3个,无对应位置:
# TypeError: func() takes 2 positional arguments but 3 were given
# 案例 【*args后的参数,必须是关键字参数:自定义或者是批量】
def func(a, *args, b):
    pass

func(1, 2, 3)   # 报错!b 必须显式指定为关键字参数keyword-only argument
func(1, 2, b=3) # 正确

e.参数传递的混淆:位置vs关键字

# 错误案例:
def func(a,b):
    pass
func(a=1, 2)  # 错误关键字参数在位置参数之后

# 正确案例:
func(1, b=1) # 位置参数在前,关键字参数在后

f.【使用总结】

  • 默认参数用不可变对象(如 None、数字、字符串)。
  • 严格遵循参数顺序:必选 → 默认 → *args → 命名关键字 → **kwargs
  • 明确参数类型:用命名关键字参数强制接口清晰性。
  • 避免参数名与内置函数冲突
  • 理解可变/不可变参数的传递机制

2.函数的作用域

  • 全局变量global
  • 局部变量
  • nonlocal关键字

a.全局变量

  • 定义:在函数外部定义的变量,整个程序都可以访问

  • 作用域:全局作用域,整个文件内有效

  • 关键字global

  • 缺点:滥用全局变量可能会导致代码耦合度过高,难以维护

# 案例1 :函数内部访问全局变量
x = 10  # 全局变量

def func():
    print(x)  # 函数内部直接可以访问全局变量
func()  # 输出10

# 错误案例:在函数内部修改全局变量
def func2():
    x = 20  # 为局部变量,并否全局变量
    print(x)
func2()  # 输出20 
print(x)  # 访问全局变量   输出10

# 案例2: 函数内部修改全局变量
def func1():
    global x  # 函数内部修改全局变量
    x = 20
    print(x)
func1()  # 输出20
print(x) # 访问全局变量  输出20(你已经在函数内部使用global进行修改了) ,

b.局部变量

  • 定义: 在函数内部定义的变量,只在函数内部有效
  • 作用域: 函数内部
  • 特点
    • 函数执行结束后,局部变量会被销毁
    • 不同函数中的同名局部变量互不影响
# 案例
def func():
    y = 5  # 局部变量,只在func内部有效
    print(y)

y = 10  # 全局变量
print(y)

func()

c.nonlocal关键字

  • 作用:在嵌套函数中,声明变量属于外层函数的作用域,并允许修改它
  • 使用场景:闭包、多层嵌套函数中共享状态
  • 限制
    • 外层函数必须定义该变量
    • 只能用于嵌套函数中(python3)
# 案例
def outer()
    z = 10
    print(z)
    def inner():
        nonlocal z #声明 z属于外层函数
        z = 20
    inner()
    print(z) # 输出 20

outer()

d.【核心原则】

尽量使用局部变量,避免全局变量;需要共享状态时,优先用 nonlocal 或类(Class)替代全局变量。

3.闭包与装饰器

a.闭包

  • 定义:指在一个内部函数捕获并保存外部函数作用域中的变量,即使外部函数已经执行完毕。 闭包的核心让内部函数“记住“并记住它被定义的环境

  • 条件

    • 必须是在嵌套函数中
    • 内部函数必须引用外部函数的变量
    • 外部函数必须返回内部函数
    # 案例:
    def outer_function(arg):
    def inner_function():
        print(arg)
    return inner_function
    
    func = outer_function('hello world!')
    func()
  • 使用场景

    • 封装私有数据:通过闭包隐藏变量,避免全局污染
    • 延迟 计算:计算周期稍后执行
    • 工厂模式:动态生成不同行为函数
  • 注意事项

    • 变量修改:Python 3 中需用 nonlocal 声明修改外部变量,Python 2 中需用可变对象(如列表)绕过限制。
    • 循环陷阱:在循环中创建闭包时,所有闭包可能共享同一变量(需用默认参数或立即绑定解决)。

b.装饰器

  • 定义:是一个接收函数作为参数,返回新函数的高阶函数。用于在不修改原函数代码的前提下增强其功能。装饰器本质上是闭包的一种应用。其中@simple_decorator相当于my_func = simple_decorator(my_func)

    # 示例
    def simple_decorator(func):
    def wrapper():
        print('函数回调之前')
        func()
          print('函数回调之后')
      return wrapper
    
    @simple_decorator
    def my_func():
      print('函数执行.....')
  • 处理参数和返回值

    # 案例:装饰器兼容任何参数的函数
    def universal_decorator(func):
      def wrapper(*args, **kwargs):
          result = func(*args, **kwargs)
          return result
      return wrapper
  • 带参数的装饰器:需要三层嵌套

    # 案例:重复函数执行的次数
    def repeat(n_times):
      def decorator(func):
          def wrapper(*args, **kwargs):
              for _ in range(n_times):
                func(*args, **kwargs)        
          return wrapper
      return decorator
  • 使用场景

    • 日志记录:记录函数调用的信息
    # 案例:记录函数的调用信息
    import functools
    def log(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            print(f'调用函数:{func.__name__},参数:{args}, {kwargs}')
            result = func(*args, **kwargs)
            print(f"函数 {func.__name__} 执行完毕")
            return result
        return wrapper
    
    @log       
    def add(a,b):
        return a+b
    
    print(add)
    • 性能测试:统计函数执行时间
    # 案例:记录函数执行的运行时间
    
    """
        实现:函数运行的时间的记录
    """
    import time
    import functools
    
    def log_execution_time(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.perf_counter()
            func(*args, **kwargs)
            end_time = time.perf_counter()
            print('{} took:{}ms'.format(func.__name__, (end_time-start_time)*1000))
        return wrapper
    
    # func.__name__:传入的func的名字
    # (end_time - start_time)*1000  毫秒对秒的转换
    
    @log_execution_time
    def my_func():
        print('hello!') 
    
    my_func()
    • 权限校验:检查用户权限后再执行函数
    # 案例:检查用户是否有权限执行
    def check_admin(user_type):
        def decorator(func):
            def wrapper(*args, **kwargs):
                if user_type != "admin":
                    raise PermissionError("无权限操作!")
                return func(*args, **kwargs)
            return wrapper
        return decorator
    
    @check_admin(user_type="admin")
    def delete_file(filename):
        print(f"删除文件: {filename}")
    
    delete_file("test.txt")  # 正常执行
    
    @check_admin(user_type="user")
    def read_file(filename):
        print(f"读取文件: {filename}")
    
    read_file("data.txt")  # 抛出 PermissionError
    
    • 缓存:存储函数结果避免重复计算
    # 案例:佩波那契数列,但未添加新的东西,让其计算
    # 避免重新计算的原理:冲cache取出,应用到my_func函数吗
    
    import functools
    
    """保存结果"""
    def cache_results(func):
        cache = {}
        @functools.wraps(func)
        def wrapper(n):
            cache[n] = my_func(n)
            return cache
        return wrapper
    
    def my_func(n):
        if 2 > n >= 0:
            return n
        return my_func(n - 1) + my_func(n - 2)
    
    • 事物管理:确保数据库操作的原子性

4.lambda匿名函数

a.基本语法

lambda arguments:expression
  • 匿名性:没有函数名,适合一次性使用

  • 单表达式:只能包含一个表达式,没有return语句,自动返回结果

  • 无复杂逻辑:不能包含多行代码,条件分支(除非是三元表达式

  • 函数对象:可以赋值给变量

  • 作用域:可以访问外层作用域的变量(包括全局变量)

注意:闭包中的延迟绑定问题,例如在循环中创建 lambda 时,变量可能最终共享同一个值

b.使用场景

  • 高阶函数的参数

    • map()
    • filter()
    • sorted()
  • 快熟定义简单的函数

    # 案例:计算数的平方
    squares = list[map(lambda x:x**2,[1,2,3])]
  • 动态参数绑定

    # 案例:在GUI或回调中传递参数
    button.bind("<Button-1>", lambda event: callback(param1, param2))
  • 字典排序或操作

    d = {"apple": 3, "banana": 1, "cherry": 2}
    sorted_items = sorted(d.items(), key=lambda item: item[1]
  • 闭包与延迟计算

    # 结合默认参数"冻结"变量值(解决循环中变量共享的问题)
    funcs = [(lambda x=i: x) for i in range(3)]

免费评分

参与人数 2吾爱币 +2 热心值 +2 收起 理由
umum + 1 + 1 谢谢@Thanks!
melooon + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

beihanwang 发表于 2025-3-14 15:22
感谢分享
zengcong 发表于 2025-3-14 15:56
xiaoweiyihei 发表于 2025-3-14 16:01
微笑男孩 发表于 2025-3-14 16:10
感谢楼主分享
xiaopanggege 发表于 2025-3-14 16:18
不错不错,感谢分享
毒见 发表于 2025-3-14 16:59
感谢分享,已收藏
zouya1990 发表于 2025-3-14 23:41
不错,记录了你的重点知识点
Fridaymong 发表于 2025-3-15 00:09
很详细,感谢分享
JeremyHou 发表于 2025-3-15 09:51
谢谢,感谢分享,很详细
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-20 03:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表