我正在尝试创建一个可以跟踪该类实例之间的基本连接操作的类。请参阅下面的最小可重现示例
from __future__ import annotations
from typing import Literal
class Block():
jointype_lookup = {'both': '>', 'right': '>>', 'left': '<<'}
def __init__(self, name):
self.name = name
self.join_stack = [self]
self.join_stack_types = []
@classmethod
def _from_join_opertation(cls, block1: Block, block2: Block, join_type: Literal['left', 'right', 'both']):
self = cls.__new__(cls)
self.join_stack = block1.join_stack + block2.join_stack
self.join_stack_types = block1.join_stack_types + [join_type] + block2.join_stack_types
return self
def __gt__(self, other: Block):
# join both
return_graph_obj = Block._from_join_opertation(self, other, 'both')
return return_graph_obj
def __rshift__(self, other: Block):
# join right
return_graph_obj = Block._from_join_opertation(self, other, 'right')
return return_graph_obj
def __lshift__(self, other: Block):
# join left
return_graph_obj = Block._from_join_opertation(self, other, 'left')
return return_graph_obj
def __str__(self):
command = f"{self.join_stack[0].name}"
for i, type in enumerate(self.join_stack_types):
command += f" {self.jointype_lookup[type]} {self.join_stack[i+1].name}"
return command
command = Block('oxygen') >> Block('hydrogen') >> Block('helium') >> Block('carbon')
print(command)
# output: oxygen >> hydrogen >> helium >> carbon
command = Block('oxygen') << Block('hydrogen') << Block('helium') << Block('carbon')
print(command)
# output: oxygen << hydrogen << helium << carbon
command = Block('oxygen') > Block('hydrogen') > Block('helium') > Block('carbon')
print(command)
# output: helium > carbon
最后一个例子就是问题所在。我可以通过将每个连续操作括在括号中来解决这个问题(这对于我的用例来说并不理想),但我热衷于理解为什么比较运算符似乎与其他运算符的工作原理根本不同,以及是否有办法改变他们的行为
使用原始方法进行连接操作,从而允许链接或使用不同的符号进行链接,但确保它们不与内置运算符冲突。
示例:
# Usage
command1 = Block('oxygen').join_right(Block('hydrogen')).join_right(Block('helium')).join_right(Block('carbon'))