Python 切片如何区分切片参数和默认参数(例如,x[i:] 与 x[i:None])



假设variable = None,如何以编程方式区分以下切片语法(具有相同的效果(?

obj[variable:]
obj[variable:None]
obj[:variable]
obj[None:variable]
obj[:]
obj[::]
obj[None:None]
obj[None:None:None]

我正在尝试自定义我的类的__getitem__方法,以[ab]使用切片语法进行高级索引(语法糖(,并希望以不同的方式处理不同的切片语法,因为我需要大量的语法糖......(这可能不是一个好的做法,但只是为了实验......

def __getitem__(self, slice_obj):
    # slice_obj will be `slice(None, None, None)` for all 
    # `obj[variable:]`, `obj[:variable]` and `obj[:]`

我们可以看到使用 dis 库有不同的切片操作码:

https://docs.python.org/2/library/dis.html#opcode-SLICE+0

SLICE+0(( 实现 TOS = TOS[:]。

SLICE+1(( 实现 TOS = TOS1[TOS:]。

SLICE+2(( 实现 TOS = TOS1[:TOS]。

SLICE+3(( 实现 TOS = TOS2[TOS1:TOS]。

那么任何人都可以使用一些内省技巧来告诉不同的语法(inspect, dis, ast,等(吗?

进一步的问题

如何分辨函数中的传入参数和默认参数? 例如,

def add(x, delta=1):
    return x + delta

在函数add内部,我们如何判断它被称为add(x)还是add(x, 1)

友情链接

[我们可以为切片使用唯一的、不同的默认参数(除了 None(吗?

https://docs.python.org/2/c-api/slice.html#c.PySlice_Newhttp://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/object.html#slice_nil-spec

任何评论/解决方法/黑客不胜感激!

给定一个slice对象,无法确定使用哪种类型的索引表达式来创建它。从a[:14]创建的slicea[None:14]或文字slice(None, 14)创建的没有区别。

但是,如果您想变得有点混乱(并且很多不可移植(,那么通过查看父帧中的当前操作码,您可能会获得一些可靠的结果:

import sys, dis
class Moo(object):
    def __getitem__(self, i):
        parent_frame = sys._getframe().f_back
        accessing_opcode = parent_frame.f_code.co_code[parent_frame.f_lasti]
        return "This __getitem__ was invoked by way of a %s instruction" 
                % dis.opname[ord(accessing_opcode)]

这将给出如下结果:

>>> m = Moo()
>>> m[5]
'This __getitem__ was invoked by way of a BINARY_SUBSCR instruction'
>>> m[5:]
'This __getitem__ was invoked by way of a SLICE+1 instruction'
>>> m[:5]
'This __getitem__ was invoked by way of a SLICE+2 instruction'
>>> m[5:5]
'This __getitem__ was invoked by way of a SLICE+3 instruction'
>>> m[:5:]
'This __getitem__ was invoked by way of a BINARY_SUBSCR instruction'
>>> m[1:5:2]
'This __getitem__ was invoked by way of a BINARY_SUBSCR instruction'

显然,如果显式调用您的__getitem__方法,这将不太有用,但也许它会满足您的需求。

对于确定调用函数的第二部分:

import inspect
>>> def add(a, b=0):
...     return a + b
... 
>>> inspect.getargspec(add)
(['a', 'b'], None, None, (0,))
>>> len(inspect.getargspec(add)[0])
2

最新更新