如何使用签名([start ,] stop [, step])实现python方法,即左侧的默认关键字参数 [英] How to implement python method with signature like ([start ,] stop [, step]), i.e. default keyword argument on the left
问题描述
自从在 python 3.X 中 build-id range()
函数返回的不再是一个列表而是一个可迭代的,当我使用 range()
时,一些旧代码失败了方便地生成我需要的列表.
所以我尝试像这样实现我自己的 lrange
函数:
def lrange(start = 0, stop, step = 1):ret = []而开始 <停止:ret.append(开始)开始 += 步骤返回 ret
给我一个非默认参数遵循默认参数"解释器错误.
如果我查看 Python 的 range() 似乎是可能的.
我发布这个问题主要是因为我想知道是否/如何自己实现具有这样签名的函数
快速解答
这个问题在我刚开始学习 Python 的时候就出现了,我觉得这里记录一下方法是值得的.仅使用一张支票来模拟原始行为.
def list_range(start, stop=None, step=1):如果停止是无:开始,停止 = 0,开始返回列表(范围(开始,停止,步骤))
我认为这个解决方案比使用所有关键字参数或 *args
更优雅.
说明
使用哨兵
正确执行此操作的关键是使用哨兵对象来确定您是否获得第二个参数,如果没有,则在将第一个参数移至第二个参数的同时提供第一个参数的默认值.
None
,作为 Python 的空值,是一个很好的最佳实践哨兵,检查它的惯用方法是使用关键字 is
,因为它是一个单例.
带有适当文档字符串的示例,声明签名/API
def list_range(start, stop=None, step=1):'''列表范围(停止)list_range(开始,停止,步骤)返回从开始(默认为 0)到停止的整数列表,逐步递增(默认为 1).'''如果停止是无:开始,停止 = 0,开始返回列表(范围(开始,停止,步骤))
演示
<预><代码>>>>列表范围(10)[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>>list_range(5, 10)[5, 6, 7, 8, 9]>>>list_range(2, 10, 2)[2, 4, 6, 8]如果没有给出参数,它会引发错误,这与这里的全关键字解决方案不同.
警告
顺便说一句,我希望这只是由读者从理论角度考虑,我不认为这个功能值得维护,除非在中央规范位置使用以使代码在 Python 2 和3. 在 Python 中,使用内置函数将范围物化为列表非常简单:
Python 3.3.1(默认,2013 年 9 月 25 日,19:29:01)[GCC 4.7.3] 在 Linux 上输入帮助"、版权"、信用"或许可证"以获取更多信息.>>>列表(范围(10))[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Since in python 3.X the build-id range()
function returns no longer a list but an iterable, some old code fails as I use range()
to conveniently generate lists I need.
So I try to implement my own lrange
function like this:
def lrange(start = 0, stop, step = 1):
ret = []
while start < stop:
ret.append(start)
start += step
return ret
giving me a "non-default argument follows default argument" interpreter error.
If I look at Python's range() it seems to be possible.
I posted this question mainly because I was wondering if/how one can implement a function with such a signature on his own
Quick Answer
This question popped up when I first started learning Python, and I think it worthwhile to document the method here. Only one check is used to simulate original behavior.
def list_range(start, stop=None, step=1):
if stop is None:
start, stop = 0, start
return list(range(start, stop, step))
I think this solution is a bit more elegant than using all keyword arguments or *args
.
Explanation
Use a Sentinel
The key to getting this right is to use a sentinel object to determine if you get a second argument, and if not, to provide the default to the first argument while moving the first argument to the second.
None
, being Python's null value, is a good best-practice sentinel, and the idiomatic way to check for it is with the keyword is
, since it is a singleton.
Example with a proper docstring, declaring the signature/API
def list_range(start, stop=None, step=1):
'''
list_range(stop)
list_range(start, stop, step)
return list of integers from start (default 0) to stop,
incrementing by step (default 1).
'''
if stop is None:
start, stop = 0, start
return list(range(start, stop, step))
Demonstration
>>> list_range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list_range(5, 10)
[5, 6, 7, 8, 9]
>>> list_range(2, 10, 2)
[2, 4, 6, 8]
And it raises an error if no arguments are given, unlike the all-keyword solution here.
Caveat
By the way, I hope this is only considered from a theoretical perspective by the reader, I don't believe this function is worth the maintenance, unless used in a central canonical location to make code cross-compatible between Python 2 and 3. In Python, it's quite simple to materialize a range into a list with the built-in functions:
Python 3.3.1 (default, Sep 25 2013, 19:29:01)
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
这篇关于如何使用签名([start ,] stop [, step])实现python方法,即左侧的默认关键字参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!