如何编写一个切片的函数?

时间:2015-04-25 08:02:04

标签: python numpy slice

我想在Python中编写一个以切片作为参数的函数。理想情况下,用户可以按如下方式调用该函数:

foo(a:b:c)

不幸的是,Python不允许使用此语法 - 只允许a:b:c使用[],而不是()

因此,我发现我的功能有三种可能性:

  1. 要求用户使用切片“构造函数”(其中s_的行为类似于the version provided by numpy):

    foo(slice(a, b, c))
    foo(s_[a:b:c])
    
  2. 将我的函数逻辑放入__getitem__方法:

    foo[a:b:c]
    
  3. 放弃尝试切片并单独开始,停止和步骤:

    foo(a, b, c)
    
  4. 有没有办法让原始语法起作用?如果不是,首选哪种解决方法语法?或者还有另一种更好的选择吗?

3 个答案:

答案 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()

如果没有真正的上下文,很难给出令人信服的例子,因为你试图用直观有意义的名字命名相关的东西,让你编写明确的代码,并且相对较短。

如果你真的只是在片上自己编写一个函数,那么:

  1. 您的函数修改切片,返回不同的切片:

    bar[foo(a:b:c)]
    

    如果是这种情况,无论您选择哪种有效语法,都会让人感到有些困惑。如果你的目标是广泛的Python程序员,你可能不想使用切片。

  2. 您的函数确实在整数片上运行,因此您可以使用临时对象进行显式操作:

    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个属性(stepstopindices)和方法getitem。它是理解这些价值观的np.s_方法。

np.lib.index_tricks以及__getitem__中的其他函数/类是slicenp.r_[3:4:10j] np.linspace(3,4,10) 如何用于扩展(或简化)索引的很好示例。例如,这些是等价的:

foo(a,b,c)

对于np.arange()语法,非常常见的range使用它。与xrangestart/step/stop一样。因此,您和您的用户应该非常熟悉它。

由于替代方案最终都会为您提供a:b:c三个值,因此它们在功能上相同(速度快)。因此,选择取决于用户偏好和熟悉程度。

虽然你的函数不能直接采用s_符号,但可以编写它来处理各种输入 - 一个切片,三个位置参数,一个元组,一个切片元组(来自{{ 1}})或关键字参数。遵循基本的numpy索引,您可以区分元组和列表。