魔法变量*args 和 **kwargs

本文详细介绍了Python中*args和**kwargs的使用方法及应用场景,包括如何在函数定义中使用它们来接受不定数量的参数,以及如何在调用函数时使用它们来传入列表或字典类型的参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        其实并不是必须写成*args**kwargs。 只有变量前面的 *(星号)才是必须的. 你也可以写成*var**vars. 而写成*args**kwargs只是一个通俗的命名约定。

*args 的用法

*args**kwargs 主要用于函数定义。 你可以将不定数量的参数传递给一个函数。

这里的不定的意思是:预先并不知道, 函数使用者会传递多少个参数给你, 所以在这个场景下使用这两个关键字。 *args 是用来发送一个非键值对的可变数量的参数列表给一个函数.

这里有个例子帮你理解这个概念:

def test_var_args(f_arg, *argv):
    print("first normal arg:", f_arg)
    for arg in argv:
        print("another arg through *argv:", arg)

test_var_args('yasoob', 'python', 'eggs', 'test')

这会产生如下输出:

first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test

**kwargs 的用法

**kwargs 允许你将不定长度的键值对, 作为参数传递给一个函数。 如果你想要在一个函数里处理带名字的参数, 你应该使用**kwargs

这里有个让你上手的例子:

def greet_me(**kwargs):
    for key, value in kwargs.items():
        print("{0} == {1}".format(key, value))


>>> greet_me(name="yasoob")
name == yasoob

现在你可以看出我们怎样在一个函数里, 处理了一个键值对参数了。

这就是**kwargs的基础, 而且你可以看出它有多么管用。 接下来让我们谈谈,你怎样使用*args**kwargs来调用一个参数为列表或者字典的函数。

使用 *args**kwargs 来调用函数

我们将看到怎样使用*args**kwargs 来调用一个函数。 假设,你有这样一个小函数:

def test_args_kwargs(arg1, arg2, arg3):
    print("arg1:", arg1)
    print("arg2:", arg2)
    print("arg3:", arg3)

你可以使用*args**kwargs来给这个小函数传递参数。 下面是怎样做:

# 首先使用 *args
>>> args = ("two", 3, 5)
>>> test_args_kwargs(*args)
arg1: two
arg2: 3
arg3: 5

# 现在使用 **kwargs:
>>> kwargs = {"arg3": 3, "arg2": "two", "arg1": 5}
>>> test_args_kwargs(**kwargs)
arg1: 5
arg2: two
arg3: 3
标准参数与*args、**kwargs在使用时的顺序

那么如果你想在函数里同时使用所有这三种参数, 顺序是这样的:

some_func(fargs, *args, **kwargs)

什么时候使用它们?

最常见的用例是在写函数装饰器的时候。

此外它也可以用来做猴子补丁(monkey patching)。猴子补丁的意思是在程序运行时(runtime)修改某些代码。 打个比方,你有一个类,里面有个叫get_info的函数会调用一个API并返回相应的数据。如果我们想测试它,可以把API调用替换成一些测试数据。例如:

import someclass

def get_info(self, *args):
    return "Test data"

someclass.get_info = get_info

转载于:https://www.cnblogs.com/linkxu1989/p/6699367.html

Traceback (most recent call last): File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\numpy\_core\fromnumeric.py", line 57, in _wrapfunc return bound(*args, **kwds) ^^^^^^^^^^^^^^^^^^^^ TypeError: '<' not supported between instances of 'datetime.datetime' and 'str' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\11685159c\PycharmProjects\PythonProject\特征相关性搜寻\test.py", line 61, in <module> corr, p_val = spearmanr(df[col], y, nan_policy='omit') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\scipy\stats\_stats_py.py", line 5291, in spearmanr a_ranked = np.apply_along_axis(rankdata, axisout, a) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\numpy\lib\_shape_base_impl.py", line 393, in apply_along_axis res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\scipy\stats\_stats_py.py", line 10212, in rankdata ranks = _rankdata(x, method) ^^^^^^^^^^^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\scipy\stats\_stats_py.py", line 10237, in _rankdata j = np.argsort(x, axis=-1, kind=kind) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\numpy\_core\fromnumeric.py", line 1260, in argsort return _wrapfunc( ^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\numpy\_core\fromnumeric.py", line 66, in _wrapfunc return _wrapit(obj, method, *args, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\11685159c\PycharmProjects\PythonProject\.venv\Lib\site-packages\numpy\_core\fromnumeric.py", line 46, in _wrapit result = getattr(arr, method)(*args, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: '<' not supported between instances of 'datetime.datetime' and 'str'
07-01
### 问题分析 在使用 `scipy.stats.spearmanr` 计算斯皮尔曼相关性系数时,出现的错误信息为: ``` TypeError: '<' not supported between instances of 'datetime.datetime' and 'str' ``` 该错误表明,在计算过程中,程序尝试对一个 `datetime.datetime` 类型对象一个字符串(`str`)进行比较操作(即 `<` 或 `>`),而 Python 不允许这两种类型之间直接比较。这种错误通常出现在数据预处理阶段,特别是在使用 `pandas` 处理包含时间戳的列时。 ### 原因与解决方案 1. **确保所有列的数据类型一致且为数值型** 斯皮尔曼相关性系数基于变量的排序关系进行计算,因此输入数据必须是可排序的数值类型。若某列中存在 `datetime` 或 `str` 类型,则会导致排序失败[^2]。 解决方法:将非数值列转换为适当的格式或排除这些列。 示例代码: ```python import pandas as pd from scipy.stats import spearmanr # 假设 df 是原始 DataFrame,其中 'date' 列为 datetime 类型 df = pd.DataFrame({ 'kh': [1, 2, 3], 'last_transaction_date': pd.to_datetime(['2023-01-01', '2023-02-01', '2023-03-01']), 'frequency': [5, 10, 15], 'monetary_value': [100, 200, 300] }) # 排除 datetime 列后计算斯皮尔曼相关性 numeric_df = df.select_dtypes(include=['number']) corr_matrix = numeric_df.corr(method='spearman') print(corr_matrix) ``` 2. **检查并清理数据中的混合类型字段** 若某一列中同时包含 `datetime` `str` 类型的数据,也会导致比较异常。应统一该列的数据类型。 示例代码: ```python # 确保 'date' 列为统一的 datetime 类型 df['date'] = pd.to_datetime(df['date'], errors='coerce') ``` 3. **避免将时间戳作为相关性分析的输入变量** 时间戳本身并不适合作为斯皮尔曼相关性的输入变量,除非将其转换为相对数值(如“天数差”或“时间戳的整数表示”)。 示例代码: ```python # 将 datetime 转换为自某个起始日期以来的天数 reference_date = df['last_transaction_date'].min() df['days_since_reference'] = (df['last_transaction_date'] - reference_date).dt.days # 使用转换后的数值列进行相关性分析 spearman_corr, p_value = spearmanr(df['days_since_reference'], df['monetary_value']) print(f"Spearman Correlation: {spearman_corr}, p-value: {p_value}") ``` 4. **使用魔法方法或自定义排序函数时需注意类型一致性** 若在自定义排序逻辑中使用了魔法方法(如 `__lt__`),则必须确保参与比较的对象具有相同的类型。Python 官方文档指出,当不同类型的对象进行比较时,会抛出 `TypeError` 异常[^3]。 示例代码: ```python class CustomObject: def __init__(self, value): self.value = value def __lt__(self, other): if not isinstance(other, CustomObject): raise TypeError("Can only compare with CustomObject instances") return self.value < other.value ``` ### 总结 上述错误的根本原因是尝试在不兼容的数据类型之间进行比较操作。解决此类问题的关键在于:确保所有用于计算斯皮尔曼相关性的数据均为数值类型;清理混合类型字段;以及合理处理时间戳等特殊数据形式。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值