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


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

foo(a:b:c)

不幸的是,Python不允许使用这种语法 - 使用 a:b:c 只允许进入 []不是 ()

因此,我认为我的功能有三种可能性:

  1. 要求用户使用切片“构造函数”(其中 s_ 表现得像 numpy提供的版本):

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

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

    foo(a, b, c)
    

有没有办法让原始语法工作?如果不是,首选哪种解决方法语法?或者还有另一种更好的选择吗?


4096
2018-04-25 08:02


起源

我会使用开始,停止和步骤设置默认值 - Padraic Cunningham
这主要是基于意见的?这是一个完全有效的问题。 - Games Brainiac
我认为使用时没有任何缺点 foo(a,b,c) 而不是 foo(a:b:c)。 - TigerhawkT3


答案:


不要让用户感到惊讶。

如果您使用切片语法与开发人员对切片语法的期望一致,那么同一个开发人员将期望使用方括号操作,即 __getitem__() 方法。

如果相反,返回的对象不是原始对象的切片,如果你坚持使用,人们会感到困惑 __getitem__() 解。使用函数调用 foo(a, b, c),根本不提切片,如果有意义,可选择指定默认值。


10
2018-04-25 08:27





切片在表达为切片时更有意义。因此,另一种选择是更加面向对象:创建一个表示您的切片的临时对象,并将您的函数作为它的一种方法。

例如,如果你的功能是真的:

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
2018-05-26 21:38





指某东西的用途 [a:b:c] 就像你注意到的那样,是一种语法的东西。口译员提出了一个问题 syntax error 对于 (a:b:c) 马上,在您的代码有机会对值进行操作之前。没有重写解释器,没有办法绕过这种语法。

值得记住的是,口译员会进行翻译 foo[a:b:c] 至

foo.__getitem__(slice(a,b,c))

slice 对象本身并不是很复杂。它只有3个属性(startstepstop)和方法 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 直接表示法,它可以编写来处理各种输入 - 一个切片,3个位置参数,一个元组,一个切片元组(从 s_)或关键字参数。并遵循基本 numpy 索引你可以区分元组和列表。


0
2018-04-25 17:09