范围的奇怪论点
Posted
技术标签:
【中文标题】范围的奇怪论点【英文标题】:the strange arguments of range 【发布时间】:2013-03-30 07:17:47 【问题描述】:python3 中的 range 函数接受三个参数。其中两个是可选的。所以参数列表看起来像:
[开始],停止,[步骤]
这意味着(如果我错了,请纠正我)在非可选参数之前有一个可选参数。但是,如果我尝试定义这样的函数,我会得到:
>>> def foo(a = 1, b, c = 2):
print(a, b, c)
SyntaxError: non-default argument follows default argument
这是我作为“普通”python 用户无法做到的事情,还是我可以以某种方式定义这样的函数?当然我可以做类似的事情
def foo(a, b = None, c = 2):
if not b:
b = a
a = 1
但例如帮助功能会显示奇怪的信息。所以我真的很想知道是否可以定义一个像内置range
这样的函数。
【问题讨论】:
见***.com/a/4137838/568777 如你所知,真正的答案是range
是一个 C 函数,由于某种原因它没有与 python 相同的规则(很高兴知道为什么)。人们可能会因为我的建议而讨厌我,但我这样做是为了范围,因为我对事物的顺序有一个糟糕的记忆。 Imo 这应该不是问题,所以我正在修复它:range(*'start':0,'stop':10,'step':2.values())
【参考方案1】:
range()
采用 1 个位置参数和两个可选参数,解释这些参数的解释取决于您传入的参数数量。
如果只传入 一个 参数,则假定为 stop
参数,否则将第一个参数解释为开始。
实际上,range()
、coded in C 采用可变数量的参数。你可以这样模拟:
def foo(*params):
if 3 < len(params) < 1:
raise ValueError('foo takes 1 - 3 arguments')
elif len(params) == 1
b = params[0]
elif:
a, b = params[:2]
c = params[2] if len(params) > 2 else 1
但你也可以只交换参数:
def range(start, stop=None, step=1):
if stop is None:
start, stop = 0, start
【讨论】:
你的最后一个例子不起作用。 TypeError: range() 不接受关键字参数 @RobSmallshire:最后一个例子是range()
的 python 替换。我使用关键字参数来模拟range()
采用的可选参数;另一种方法是使用 *args
包罗万象的参数并从中解析最多 2 个值,但这会变得更加冗长。这是我回答中的第一个示例。
@RobSmallshire:OP 试图用关键字参数模拟 range()
行为,第二部分是说明如何通过使用关键字参数来实现行为(接受 1 到 3 个位置参数) , 在python代码中.
所以,这只是因为它的 C 编码版本采用 *params
而不是实际定义参数......但他们为什么要这样编码呢?我看不出有理由在参数上使用*params
,尤其是如果参数的长度大于 3 时函数将返回错误。看起来就像是非常草率的编码......是因为它更快吗?对我来说,它应该被编码为range(PyObject *stop, PyObject *start, PyObject *step)
,而不是处理这个问题。对我来说,这似乎是一个非常奇怪的决定......
@CoreyLevinson:不,因为那样你就必须始终指定起始值和步长值。 Python 核心开发人员明确选择支持range(stop)
和range(start, stop)
。【参考方案2】:
range
不接受关键字参数:
range(start=0,stop=10)
TypeError: range() takes no keyword arguments
它需要 1、2 或 3 个位置参数,它们根据它们的数量进行评估:
range(stop) # 1 argument
range(start, stop) # 2 arguments
range(start, stop, step) # 3 arguments
即无法创建具有已定义 stop
和 step
以及默认 start
的范围。
【讨论】:
有没有办法让range
函数在不编写虚拟函数或其他东西的情况下接受参数...?
找到了我自己的问题的答案:range(*'start':0,'stop':10,'step':2.values())
【参考方案3】:
def foo(first, second=None, third=1):
if second is None:
start, stop, step = 0, first, 1
else:
start, stop, step = first, second, third
【讨论】:
【参考方案4】:你现在知道,真正的答案是range
是一个 C 函数,由于某种原因它没有与 python 相同的规则(很高兴知道为什么)。
人们可能会因为我的建议而讨厌我,但我这样做是为了范围,因为我对事物的顺序有一个糟糕的记忆。我认为这应该不是问题,所以我正在修复它:
range(*'start':0,'stop':10,'step':2.values())
我把它做成单列的原因是因为我不想定义一个需要在任何地方定义或在任何地方导入的范围函数。这是纯python。
【讨论】:
以上是关于范围的奇怪论点的主要内容,如果未能解决你的问题,请参考以下文章