Python slice 如何区分切片参数和默认参数(例如,x[i:] vs. x[i:None])?
Python slice how to distinguish slice arguments and default arguments (e.g., x[i:] vs. x[i:None])?
假设variable = None
,如何以编程方式区分以下切片语法(具有相同的效果)?
obj[variable:]
obj[variable:None]
obj[:variable]
obj[None:variable]
obj[:]
obj[::]
obj[None:None]
obj[None:None:None]
我正在尝试自定义 class 的 __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() Implements TOS = TOS[:].
SLICE+1() Implements TOS = TOS1[TOS:].
SLICE+2() Implements TOS = TOS1[:TOS].
SLICE+3() Implements TOS = TOS2[TOS1:TOS].
所以任何人都可以使用一些内省技巧来分辨不同的语法(inspect, dis, ast,
等)吗?
进一步问题:
如何区分函数中的传入参数和默认参数?例如,
def add(x, delta=1):
return x + delta
在add
函数中,我们如何判断它是被调用为add(x)
还是add(x, 1)
?
链接:
[我们可以为 slice 使用一个独特的、不同的默认参数(None 除外)吗?]
https://docs.python.org/2/c-api/slice.html#c.PySlice_New
http://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/object.html#slice_nil-spec
任何 comments/workarounds/hacks 不胜感激!
对于第二部分,确定调用什么函数:
import inspect
>>> def add(a, b=0):
... return a + b
...
>>> inspect.getargspec(add)
(['a', 'b'], None, None, (0,))
>>> len(inspect.getargspec(add)[0])
2
给定一个 slice
对象,无法确定使用何种类型的索引表达式来创建它。从 a[:14]
创建的 slice
与 a[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__
方法被显式调用,这将没有多大帮助,但也许它会满足您的需要。
假设variable = None
,如何以编程方式区分以下切片语法(具有相同的效果)?
obj[variable:]
obj[variable:None]
obj[:variable]
obj[None:variable]
obj[:]
obj[::]
obj[None:None]
obj[None:None:None]
我正在尝试自定义 class 的 __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() Implements TOS = TOS[:].
SLICE+1() Implements TOS = TOS1[TOS:].
SLICE+2() Implements TOS = TOS1[:TOS].
SLICE+3() Implements TOS = TOS2[TOS1:TOS].
所以任何人都可以使用一些内省技巧来分辨不同的语法(inspect, dis, ast,
等)吗?
进一步问题:
如何区分函数中的传入参数和默认参数?例如,
def add(x, delta=1):
return x + delta
在add
函数中,我们如何判断它是被调用为add(x)
还是add(x, 1)
?
链接:
[我们可以为 slice 使用一个独特的、不同的默认参数(None 除外)吗?]
https://docs.python.org/2/c-api/slice.html#c.PySlice_New http://www.boost.org/doc/libs/1_39_0/libs/python/doc/v2/object.html#slice_nil-spec
任何 comments/workarounds/hacks 不胜感激!
对于第二部分,确定调用什么函数:
import inspect
>>> def add(a, b=0):
... return a + b
...
>>> inspect.getargspec(add)
(['a', 'b'], None, None, (0,))
>>> len(inspect.getargspec(add)[0])
2
给定一个 slice
对象,无法确定使用何种类型的索引表达式来创建它。从 a[:14]
创建的 slice
与 a[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__
方法被显式调用,这将没有多大帮助,但也许它会满足您的需要。