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

Python切片如何区分切片参数和默认参数(例如,x[i:]与x[i:None])?,python,indexing,syntax,slice,default-arguments,Python,Indexing,Syntax,Slice,Default Arguments,假设variable=None,如何通过编程区分以下切片语法(具有相同的效果) 我正在尝试自定义我的类的\uu getitem\uuuu方法,以[ab]使用切片语法进行高级索引(语法糖),并希望以不同的方式对待不同的切片语法,因为我需要大量的语法糖…(这可能不是一个好的实践,但仅用于实验…) 我们可以使用dis库看到不同的切片操作码: SLICE+0()实现TOS=TOS[:] SLICE+1()实现TOS=TOS1[TOS:] SLICE+2()实现TOS=TOS1[:TOS] SLICE+

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

我正在尝试自定义我的类
\uu getitem\uuuu
方法,以[ab]使用切片语法进行高级索引(语法糖),并希望以不同的方式对待不同的切片语法,因为我需要大量的语法糖…
(这可能不是一个好的实践,但仅用于实验…)

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

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)

链接

[我们是否可以为slice使用唯一的、不同的默认参数(None除外)?]


任何意见/解决方法/黑客都将不胜感激

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

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

给定一个
切片
对象,无法确定用于创建它的索引表达式的类型。从
a[:14]
创建的
slice
与由
a[None:14]
或literal
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'

显然,如果显式调用
\uuuu getitem\uuu
方法,这将没有多大帮助,但它可能会满足您的需要。

感谢@chepner指出。我试着用slice作为语法糖,我需要很多糖来表达不同的意思。。。我更新了我的问题来强调这一点。非常小心地滥用标准语法-确保当你的切片/切片背叛了正常使用时,你的API聪明度超过了任何用户认知上的不一致,特别是在那些刚刚搞清楚切片是怎么回事的新pythoner中。另外,您的API将如何处理本身是切片对象的单个参数?谢谢,我将阅读更多关于检查和试验您的方法的信息。您也可以将参数默认为某个抽象值,检查该值,如果它仍然是抽象的,则将其设置为正确的默认值!如果你有几个论点,这可能会很长!def add(a,b=6996420):如果b==6996420:b=1返回a+By,您可能在不同版本的Python中也存在问题。感谢您检查操作码的方法!这是我以前想检查的。遗憾的是,我们仍然无法区分
切片
对象与
对象的区别。正如@PaulMcGuire所评论的,我可能不得不重新思考我的语法设计。为了添加到您的好例子中,
m[slice\u obj]->“This\uu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
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'