• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
孙龙 程序员
少时总觉为人易,华年方知立业难
博客园    首页    新随笔    联系   管理    订阅  订阅
python基础知识
函数:不定长参数
# -*- coding: utf-8 -*-
# @Author  : 顾安
# @File    : 4.不定长参数.py
# @Software: PyCharm
# @Time    : 2023/11/1 21:09


"""
*args
**kwargs

可以在函数中接收不确定数量的参数

args: 可以接收不确定数量的参数, 并打包成一个元组
kwargs: 可以接收不确定数量的参数, 并打包成一个字典
"""


def func_attr(a, b, *args, **kwargs):
    print(a, type(a))
    print(b, type(b))
    print(args, type(args))
    print(kwargs, type(kwargs))


func_attr(1, 2, 3, 4, 5, name='安娜', gender='女')

"""
在函数调用的过程中如果传递的参数个数超出函数本身的新式参数则多余的参数会被args和kwargs接收
    args: 接收的是普通传参方式的多个值并打包成元组
    kwargs: 接收的是命名参数传递方式的多个值并打包成一个字典
"""

"""
在不定长参数前面的*代表的是元素值
    (1, 2, 3)

如果是**kwargs
    {name: '双双'}
"""

"""
关于不定长参数使用的注意事项
    形式参数 > 缺省参数 > *args > **kwargs
"""


def test_attr(a, *args, b=22, c=33, **kwargs):
    print(a, args, b, c, kwargs)


# 当前传参需求是a=1, b=2, c=3, args=(4,)
test_attr(1, 2, 3, 4, name='aa')


# **kwargs一定是在所有参数的最后
# def test_attr(a, *args, b=22, **kwargs, c=33):
#     print(a, args, b, c, kwargs)


# 需要在调用函数的时候确定每一个参数的具体的值
# 可以确定每一个参数的值
# 语法更严格, 每个参数必须对应一个值, 并且强制性使用命名参数
def set_attr(*, a, b, c):  # 不允许使用不定长参数
    print()


set_attr(a=1, b=2, c=3)

2 <class 'int'>
(3, 4, 5) <class 'tuple'>
{'name': '安娜', 'gender': '女'} <class 'dict'>
1 (2, 3, 4) 22 33 {'name': 'aa'}

参数拆包
# -*- coding: utf-8 -*-
# @Author  : 顾安
# @File    : 5.使用*号拆包.py
# @Software: PyCharm
# @Time    : 2023/11/1 21:52


def set_list_attr(*args):
    print(*args)


nums = [1, 2, 3]
set_list_attr(*nums)


def set_dict_attr(name, gender):
    print(name, gender)


info = {
    'name': '安娜',
    'gender': '女'
}


set_dict_attr(**info)

1 2 3
安娜 女

使用拆包的方式完成函数地址互换
# -*- coding: utf-8 -*-
# @Author  : 顾安
# @File    : 7.使用拆包的方式完成函数地址互换.py
# @Software: PyCharm
# @Time    : 2023/11/1 22:16


def test_1():
    print(1)


def test_2():
    print(2)


test_1, test_2 = test_2, test_1

test_1()
test_2()

"""
函数调用: 通过小括号的方式让python解释器找到在内存中的函数代码并运行
函数引用: 通过函数名称本身获取函数地址, 这个不是运行代码
"""

# test_1  # 引用
# test_2()  # 调用
引用传递和值传递
1. 理解引用传递和值传递
  • 值传递:在函数调用时,会把实际参数的值复制一份传递给形式参数。在函数内部对形式参数进行修改,不会影响到实际参数。
  • 引用传递:在函数调用时,传递的是实际参数的引用(也就是内存地址),而非实际参数的值。在函数内部对形式参数进行修改,会影响到实际参数。

2. Python 中 list 的引用传递示例
def modify_list(lst):
    lst.append(4)
    print("函数内部的列表:", lst)


my_list = [1, 2, 3]
print("调用函数前的列表:", my_list)
modify_list(my_list)
print("调用函数后的列表:", my_list)

在这个例子中,modify_list 函数接收一个列表作为参数。在函数内部,对传入的列表添加了一个元素 4。调用函数之后,原列表 my_list 也发生了改变,这就表明 list 是引用传递。

3. 复制列表以避免引用传递带来的影响
如果你不想让函数内部的修改影响到原列表,可以传递列表的副本,例如:
def modify_list(lst):
    lst.append(4)
    print("函数内部的列表:", lst)


my_list = [1, 2, 3]
print("调用函数前的列表:", my_list)
modify_list(my_list.copy())  # 传递列表的副本
print("调用函数后的列表:", my_list)

在这个例子中,传递给 modify_list 函数的是 my_list 的副本,所以函数内部的修改不会影响到原列表 my_list。

在 Python 里,变量的传递本质上是对象引用的传递,当你把一个对象作为参数传递给函数时,实际上传递的是该对象的引用,而非对象的值。这意味着,对于可变对象而言,函数内部对其的修改会影响到原对象,可看作是 “引用传递”;而对于不可变对象,函数内部无法修改原对象,只能创建新对象,可看作 “值传递”。除了 list 之外,下面这些数据类型也是可变对象,在传递时表现为引用传递:

下面两种类型也是引用传递

字典(dict)字典是一种无序的数据集合,它由键值对组成

集合(set)集合是一种无序且唯一的数据集合

自定义类的实例-引用传递
class MyClass:
    def __init__(self, value):
        self.value = value


def modify_instance(obj):
    obj.value = 100
    print("函数内部的实例属性值:", obj.value)


my_obj = MyClass(10)
print("调用函数前的实例属性值:", my_obj.value)
modify_instance(my_obj)
print("调用函数后的实例属性值:", my_obj.value)

在这个例子中,modify_instance 函数接收一个自定义类的实例作为参数,并在函数内部修改了实例的属性值。调用函数之后,原实例 my_obj 的属性值也发生了改变。

 















本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/articles/18800817

posted on 2025-03-30 17:00  孙龙-程序员  阅读(16)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3