我正在尝试在一个类上重载__rrshift__
方法。基本实现如下:
class A:
def __rrshift__(self, arg0):
print(f'called A.__rrshift__ with arg0={arg0}')
a = A()
42 >> a
在这里我得到了预期的结果:
called A.__rrshift__ with arg0=42
但是,如果我使用多个参数调用此方法,则仅使用最后一个参数:
'hello', 'world' >> a
哪个返回:
called A.__rrshift__ with arg0=world
如果我尝试向__rrshift__
方法添加参数,则行为不会按我预期的那样修改:
class B:
def __rrshift__(self, arg0, arg1=None):
print(f'called B.__rrshift__ with arg0={arg0}, arg1={arg1}')
b = B()
42 >> b
'hello', 'world' >> b
# called B.__rrshift__ with arg0=42, arg1=None
# called B.__rrshift__ with arg0=world, arg1=None
__rrshift__
方法是否可以考虑多个参数?
答案 0 :(得分:1)
我不确定您要做什么,但是如果您只需要提供一些args(最终是kwargs),这可能会向您展示如何实现:
class A:
def __rrshift__(self, *args):
if len(args) > 1:
print(f'called A.__rrshift__ with arg={", ".join(args)}')
else:
print(f'called A.__rrshift__ with arg={args[0]}')
a = A()
a.__rrshift__('hello', 'world')
a.__rrshift__(42)
#called A.__rrshift__ with arg=hello, world
#called A.__rrshift__ with arg=42
答案 1 :(得分:1)
恐怕不可能。
__rrshift__
,例如__add__
,__sub__
等。是二元运算符。它们正好接受两个参数:self
和whatever_other_argument
。
当然,您可以通过显式调用这些方法来欺骗系统,然后它们将能够接受所需的任意多个参数,但是如果您使用>>
,{{1} },+
等语言,那么该语言的语法将强制他们完全接受两个参数。
您可能可以通过使用-
模块修改Python语法的技巧来修改它,但这不再是Python。
根据the grammar,这是Python解析器如何查看ast
的地方:
a, b >> c
产生[sic]元组的语法中的结果似乎如下:
>>> ast.dump(ast.parse('a, b >> c'))
# I prettified this myself. The actual output of `dump` is horrendous looking.
Module(
body=[
Expr(
# Build a tuple...
value=Tuple(elts=[
Name(id='a', ctx=Load()), # ...containing `a`...
# ...and the result of a BINARY OPERATOR (RShift)...
BinOp(
left=Name(id='b', ctx=Load()), # ...which is applied to `b`...
op=RShift(),
right=Name(id='c', ctx=Load()) # ...and `c`
)
],
ctx=Load()
)
)
]
)
如您所见,然后继续解析testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
生产,然后将其解压缩到test
生产,然后到达以下生产:
expr
因此,shift_expr: arith_expr (('<<'|'>>') arith_expr)*
中的第一个test
解析为testlist_star_expr
,第二个解析为atom: NAME
。后来,最终构造了元组。