我想在Python中编写一个以切片作为参数的函数。理想情况下,用户可以按如下方式调用该函数:
foo(a:b:c)
不幸的是,Python不允许使用此语法 - 只允许a:b:c
使用[]
,而不是()
。
因此,我发现我的功能有三种可能性:
要求用户使用切片“构造函数”(其中s_
的行为类似于the version provided by numpy):
foo(slice(a, b, c))
foo(s_[a:b:c])
将我的函数逻辑放入__getitem__
方法:
foo[a:b:c]
放弃尝试切片并单独开始,停止和步骤:
foo(a, b, c)
有没有办法让原始语法起作用?如果不是,首选哪种解决方法语法?或者还有另一种更好的选择吗?
答案 0 :(得分:10)
不要让用户感到惊讶。
如果您使用切片语法与开发人员对切片语法的期望一致,那么同一个开发人员将期望使用方括号操作,即__getitem__()
方法。
如果返回的对象不是某种原始对象的切片,那么如果您坚持使用__getitem__()
解决方案,人们会感到困惑。使用函数调用foo(a, b, c)
,根本不提及切片,如果有意义,可以选择指定默认值。
答案 1 :(得分:2)
切片在被表达为切片时更有意义。所以,另一个选择是更加面向对象:创建一个代表你的切片的临时对象,并将你的函数作为它的一个方法。
例如,如果您的功能确实如此:
foo(bar, a:b:c)
或
bar.foo(a:b:c)
然后您可以将其替换为:
bar[a:b:c].foo()
如果bar[a:b:c]
已经有不同的含义,那么请提出另一个名称baz
并执行:
bar.baz[a:b:c].foo()
如果没有真正的上下文,很难给出令人信服的例子,因为你试图用直观有意义的名字命名相关的东西,让你编写明确的代码,并且相对较短。
如果你真的只是在片上自己编写一个函数,那么:
您的函数修改切片,返回不同的切片:
bar[foo(a:b:c)]
如果是这种情况,无论您选择哪种有效语法,都会让人感到有些困惑。如果你的目标是广泛的Python程序员,你可能不想使用切片。
您的函数确实在整数片上运行,因此您可以使用临时对象进行显式操作:
the_integers[a:b:c].foo()
答案 2 :(得分:0)
正如您所注意到的,使用[a:b:c]
是一种语法。在您的代码有机会对值进行操作之前,解释器会立即为syntax error
(a:b:c)
引发foo[a:b:c]
。没有重写解释器,没有办法绕过这种语法。
值得记住的是,口译员会将foo.__getitem__(slice(a,b,c))
翻译为
slice
start
对象本身并不复杂。它只有3个属性(step
,stop
,indices
)和方法getitem
。它是理解这些价值观的np.s_
方法。
np.lib.index_tricks
以及__getitem__
中的其他函数/类是slice
和np.r_[3:4:10j]
np.linspace(3,4,10)
如何用于扩展(或简化)索引的很好示例。例如,这些是等价的:
foo(a,b,c)
对于np.arange()
语法,非常常见的range
使用它。与xrange
和start/step/stop
一样。因此,您和您的用户应该非常熟悉它。
由于替代方案最终都会为您提供a:b:c
三个值,因此它们在功能上相同(速度快)。因此,选择取决于用户偏好和熟悉程度。
虽然你的函数不能直接采用s_
符号,但可以编写它来处理各种输入 - 一个切片,三个位置参数,一个元组,一个切片元组(来自{{ 1}})或关键字参数。遵循基本的numpy
索引,您可以区分元组和列表。