小甲鱼 发表于 2026-2-18 04:43:26

本主题需向作者支付 5 鱼币 才能浏览 购买主题

不二如是 发表于 2026-2-18 08:24:40

第一!

haly 发表于 2026-3-31 06:26:36

@FishC 下面代码运行后会发生什么?

def collect(**meta):
    return meta

collect(a=1, **{"a": 2})

A. 返回 {'a': 2}
B. 返回 {'a': 1}
C. TypeError:multiple values for keyword argument 'a'
D. 不会报错但结果不确定

FishC 发表于 2026-3-31 06:26:49

haly 发表于 2026-03-31 06:26
@FishC 下面代码运行后会发生什么?

def collect(* ...

下面代码运行后会发生什么?

def collect(**meta):
    return meta

collect(a=1, **{"a": 2})


运行代码会引发 TypeError,错误信息提示关键字参数 a 被多次赋值。

具体原因:

[*]函数 collect 使用 **meta 收集所有关键字参数。
[*]调用时,先传入关键字参数 a=1,再通过字典解包传入 **{"a": 2}。
[*]这相当于为同一个参数 a 提供了两个值(1 和 2),Python 不允许这种情况,因此会报错。


正确选项:C. TypeError:multiple values for keyword argument 'a'

如果想测试,可以尝试分别传入不同参数名的字典,例如:

def collect(**meta):
    return meta

print(collect(a=1, **{"b": 2}))# 输出:{'a': 1, 'b': 2}


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

haly 发表于 2026-3-31 06:27:11

@FishC 已知函数定义如下,哪一个调用不会报错?

def paint(main, *colors, theme):
    pass

A. paint("red", "blue", "dark")
B. paint("red", "blue", theme="dark")
C. paint(main="red", "blue", theme="dark")
D. paint("red", theme="dark", "blue")

FishC 发表于 2026-3-31 06:27:39

haly 发表于 2026-03-31 06:27
@FishC 已知函数定义如下,哪一个调用不会报错?

d ...

根据函数定义 def paint(main, *colors, theme):,参数含义如下:
- main:必需的位置参数。
- *colors:可变位置参数,接收任意数量的额外位置参数。
- theme:在 *colors 之后,因此是关键字唯一参数,必须通过关键字指定。

分析各选项:

[*]A. paint("red", "blue", "dark"):传递了三个位置参数,main 得到 "red",*colors 捕获 "blue" 和 "dark",但 theme 未指定,调用报错。
[*]B. paint("red", "blue", theme="dark"):传递两个位置参数 "red" 和 "blue",main 得到 "red",*colors 捕获 "blue",theme 通过关键字指定为 "dark",调用正确。
[*]C. paint(main="red", "blue", theme="dark"):关键字参数 main="red" 后跟位置参数 "blue",违反了位置参数必须在关键字参数之前的规则,调用报错。
[*]D. paint("red", theme="dark", "blue"):位置参数 "red" 后跟关键字参数 theme="dark",再跟位置参数 "blue",同样违反了位置参数不能跟在关键字参数之后的规则,调用报错。

因此,只有选项 B 不会报错。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

a247863072 发表于 2026-5-29 19:56:00

@FishC 下面代码运行后会发生什么?

nums =

def sub(a, b):
    return a - b

print(sub(nums))

A. 输出 2
B. 输出 -2
C. 输出
D. 会报 TypeError

@FishC 执行以下代码后,输出结果是什么?

def count(*nums):
    return len(nums)

print(count())

A. 0
B. 1
C. 会报错
D. None

@FishC 下面代码运行后会发生什么?

def collect(**meta):
    return meta

collect(a=1, **{"a": 2})

A. 返回 {'a': 2}
B. 返回 {'a': 1}
C. TypeError:multiple values for keyword argument 'a'
D. 不会报错但结果不确定

@FishC 执行以下代码后,输出结果是什么?

def last(*nums):
    return nums[-1]

print(last(6, 7, 8))

A. 6
B. 7
C. 8
D. 会报错

FishC 发表于 2026-5-29 19:56:11

a247863072 发表于 2026-05-29 19:56
@FishC 下面代码运行后会发生什么?

nums =

de ...

问题1: nums = def sub(a, b): return a - b print(sub(nums))
运行时,sub函数需要两个位置参数,但只传递了一个列表对象,因此Python会抛出TypeError,提示缺少必要参数b。
答案:D

问题2: def count(*nums): return len(nums) print(count())
*nums是可变参数,允许接收任意数量的参数,包括0个。此时nums是空元组,长度为0,所以输出0。
答案:A

问题3: def collect(**meta): return meta collect(a=1, **{"a": 2})
**{"a": 2}展开后等价于a=2,与前面的a=1重复传参,导致TypeError: multiple values for keyword argument 'a'。
答案:C

问题4: def last(*nums): return nums[-1] print(last(6, 7, 8))
*nums将三个参数打包成元组(6, 7, 8),索引-1返回最后一个元素8。
答案:C

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

FishC 发表于 2026-5-29 19:56:17

a247863072 发表于 2026-05-29 19:56
@FishC 下面代码运行后会发生什么?

nums =

de ...

第一个问题:
sub(nums) 调用时,函数期望两个位置参数,但只传入一个列表,因此会触发 TypeError。正确答案是 D。

第二个问题:
count() 使用 *nums 收集所有位置参数,不传入参数时 nums 为空元组,len(nums) 返回 0。正确答案是 A。

第三个问题:
collect(a=1, **{"a": 2}) 中关键字参数 a 被重复赋值(一次直接指定,一次通过解包),导致 TypeError: multiple values for keyword argument 'a'。正确答案是 C。

第四个问题:
last(6, 7, 8) 中 *nums 将三个参数收集为元组 (6, 7, 8),nums[-1] 返回最后一个元素 8。正确答案是 C。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

FishC 发表于 2026-5-29 19:56:23

a247863072 发表于 2026-05-29 19:56
@FishC 下面代码运行后会发生什么?

nums =

de ...


[*]第一题: 定义函数 sub(a, b) 需要两个参数,但调用时只传入一个列表 nums,Python 会抛出 TypeError。选项 D 正确。
[*]第二题: def count(*nums) 中的 *nums 表示接受任意数量的参数(以元组形式存储)。当调用 count() 不传参数时,nums 是空元组,len(nums) 为 0,输出 0。选项 A 正确。
[*]第三题: def collect(**meta) 接受关键字参数。调用时同时传入 a=1 和 **{"a": 2},导致参数 a 被重复赋值,引发 TypeError: multiple values for keyword argument 'a'。选项 C 正确。
[*]第四题: def last(*nums) 收集所有位置参数为元组,调用 last(6, 7, 8) 时 nums = (6, 7, 8),nums[-1] 返回最后一个元素 8。选项 C 正确。


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

FishC 发表于 2026-5-29 19:56:29

a247863072 发表于 2026-05-29 19:56
@FishC 下面代码运行后会发生什么?

nums =

de ...

第一题:
nums =
def sub(a, b):
    return a - b
print(sub(nums))
sub 函数需要两个参数,但调用时只传入了一个列表 nums(一个参数),会触发 TypeError。
答案:D

第二题:
def count(*nums):
    return len(nums)
print(count())
count() 没有传入任何参数,*nums 收集到空元组,长度 len(nums) 为 0。
答案:A

第三题:
def collect(**meta):
    return meta
collect(a=1, **{"a": 2})
调用时先传了关键字参数 a=1,又通过 **{"a": 2} 解包传入另一个 a,导致关键字参数 a 被重复赋值,引发 TypeError: got multiple values for keyword argument 'a'。
答案:C

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

a247863072 发表于 2026-5-29 20:06:14

@FishC 以下代码能否正常运行?

def greet(*names, sep):
    print(sep.join(names))

greet("Hi", "Hello", "Hey")

A. 能,输出 HiHelloHey
B. 能,输出 Hi Hello Hey
C. 不能,sep 缺少实参
D. 不能,join 方法不支持元组

FishC 发表于 2026-5-29 20:06:17

a247863072 发表于 2026-05-29 20:06
@FishC 以下代码能否正常运行?

def greet(*names, ...

答案是 C。因为函数定义中 sep 是关键字参数,必须在调用时以 sep=值 的形式传入,而调用时只给了三个位置参数,没有给 sep 赋值,所以会报错。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

a247863072 发表于 2026-5-29 20:07:55

@FishC
def greet(*names, sep):这个sep为什么是关键字参数,这个*又不是,*,而是表示names是元组的*

FishC 发表于 2026-5-29 20:08:01

a247863072 发表于 2026-05-29 20:07
@FishC
def greet(*names, sep):这个sep为什么是关 ...

在Python中,def greet(*names, sep): 这里的 *names 用于收集任意数量的**位置参数**,并打包成一个元组赋给 names。
因为所有传入的**位置参数**都会被 *names“吃掉”,所以后面定义的 sep 就无法再接收位置参数了。于是,sep 只能以**关键字参数**的形式传入,即必须写成 greet('A','B', sep='-') 这样的方式。
简单说:只要某个参数出现在 *args(这里是 *names)的**后面**,它就只能作为关键字参数使用。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

a247863072 发表于 2026-5-29 20:09:18

@FishC 那如果是def greet(**names, sep):sep也必须是关键字参数吗?如果sep在*name前或者**name前,也是关键字参数吗

FishC 发表于 2026-5-29 20:09:29

a247863072 发表于 2026-05-29 20:09
@FishC 那如果是def greet(**names, sep):sep也必须是 ...

在 Python 的函数定义中,参数顺序是有严格规则的:位置参数 -> 默认参数 -> *args(可变位置参数) -> 命名关键字参数(keyword-only) -> **kwargs(可变关键字参数)。

对于你提到的 def greet(**names, sep): 这种写法,是语法错误,因为 **names 必须放在参数列表的最后,它的后面不能再有任何参数。如果试图这样写,Python 会直接报 SyntaxError: invalid syntax。所以 sep 要么在 **names 之前,要么根本不能出现。

那如果 sep 放在 *name 前面(例如 def greet(sep, *name)),此时 sep 是一个普通位置参数,你可以通过位置或关键字传给它。

如果 sep 出现在 *name 之后、**names 之前(例如 def greet(*name, sep, **names)),那么 sep 就变成命名关键字参数(keyword-only),调用时必须显式使用关键字名称传入,不能按位置传递。

总结:
- **变参 后面不能再有其他参数,否则语法错误。
- sep 在 *变参 之前 → 位置参数(也可作关键字参数)。
- sep 在 *变参 之后、**变参 之前 → 命名关键字参数(只能通过关键字传递)。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

a247863072 发表于 2026-5-29 20:11:53

@FishC
在 Python 的函数定义中,参数顺序是有严格规则的:位置参数 -> 默认参数 -> *args(可变位置参数) -> 命名关键字参数(keyword-only) -> **kwargs(可变关键字参数)。
但是上节课学的说默认参数要放到最后,这里为什么关键字参数放到最后了呢

FishC 发表于 2026-5-29 20:12:01

a247863072 发表于 2026-05-29 20:11
@FishC
在 Python 的函数定义中,参数顺序是有严格 ...

是的,您提到的这个顺序是 Python 函数参数定义的完整规范,而“默认参数要放到最后”其实是一种简化的说法,它只针对默认参数与非默认的位置参数之间的关系。具体来说:

Python 参数顺序规则(从前往后):

[*]位置参数(必须提供,无默认值)
[*]默认参数(有默认值,但必须在所有位置参数之后)
[*]*args(收集多余的位置参数,组成元组)
[*]命名关键字参数(keyword-only,必须使用关键字形式传入,可以没有默认值,也可以有默认值,但必须放在 * 或 *args 之后)
[*]**kwargs(收集多余的关键字参数,组成字典,必须是最后一个参数)


您提到的“默认参数要放到最后”实际上是来自较早的教程,那时还没有引入 * 和 **kwargs 的完整语法。实际上,默认参数只需要保证它后面不再出现不带默认值的位置参数即可。例如:

def func(a, b=2, *args, c, d=5, **kwargs):
这里 b=2 是默认参数,后面还可以跟 *args、c(命名关键字参数)、d=5 以及 **kwargs。所以“默认参数要放到最后”指的是“在所有非默认的位置参数之后”,而不是指函数参数列表的末尾。

总结:最终的顺序是由 Python 语法强制规定的,只能按照 位置参数→默认参数→*args→命名关键字参数→**kwargs 来排列。 您的理解是正确的,默认参数并不是绝对的最后,关键字参数(尤其是命名关键字参数和 **kwargs)才是真正的最后。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 第043讲:函数(III)