【发布时间】:2020-05-12 09:22:55
【问题描述】:
我正在尝试创建一个类来处理逻辑文字,我想通过重载 __neg__() 运算符来解释否定文字:
class Literal():
def __init__(self,n):
self.name = n
self.sign = True
def __neg__(self):
self.sign = False
return self
def __repr__(self):
return self.name
没有什么太复杂的;当我定义实例A=Literal('A') 并运行命令(-A).sign 时,我现在成功地将sign 属性更改为False。但是,如果我稍后运行A.sign,则该属性仍设置为False,这是我不想要的。我希望A.sign 的值始终返回True,(-A).sign 的值始终返回False。
注意:我不能只创建一个辅助实例other 并设置other.sign = False,因为不管它的sign 值如何,对A 的任何调用都应该引用A 而不是副本。
我一直在尝试不同的想法,例如设置@property,但似乎无法弄清楚,所以我求助于互联网。提前致谢,如果您想了解更多信息,请告诉我!
编辑:
我让它返回一个新实例,就像我之前所做的那样,因为似乎每个人都同意这是最好的选择。我添加了一个由此产生的问题的示例案例,以便更清楚:
class Literal():
def __init__(self,n,s=True):
self.name = n
self.sign = s
def __neg__(self):
result = Literal(self.name, not self.sign)
return result
def __repr__(self):
return self.name
A = Literal('A')
B = Literal('B')
C = Literal('C')
print((-A).sign)
>>> False
print(B.sign)
>>> True
print((-B).sign)
>>> False
print(A.sign)
>>> True
print(B.sign)
>>> False
这行得通。但是,稍后我需要在集合列表(这代表 CNF)中收集文字列表,并且拥有单独的实例会导致问题,因为我最终会得到重复的文字:
test = [{A,-B},{B,C},{-A,C}]
lits = []
for x in test:
for i in x:
print(x,i,i.sign)
if i not in lits:
lits.append(i)
print(f'\n{test}')
print(lits)
>>> {B, A} B False
>>> {B, A} A True
>>> {B, C} B True
>>> {B, C} C True
>>> {C, A} C True
>>> {C, A} A False
>>> test: [{B, A}, {B, C}, {C, A}]
>>> lits: [B, A, B, C, A]
由于 sign 的这种实现,被否定的文字 B 和 A 被重复。
希望这能澄清我之前的笔记。
【问题讨论】:
-
不应该
__neg__返回一个 new 实例,sign设置为False? -
"注意:我不能只将第二个实例设为 other 并设置 other.sign = False,因为无论其符号值如何,对 A 的任何调用都应引用 A 而不是副本。"但是
A仍然会引用原始的A,除非您手动重新分配新对象到A...。试试看。 -
我会,但我澄清说我不能这样做,因为这会给我留下基本上两个不同值的同名实例。我可以看到这不是问题的场景,但我只需要一个具有任何相同名称的实例。如果我按照您的建议进行操作(我已经尝试过),我最终会得到两个具有不同符号值的
A文字,这不是我想要的。 -
在这种情况下你不能使用
__neg__。我想您不想使用not A.sign是有原因的?这可能是XY problem? -
要缓解多个实例的问题,您可以简单地检查名称是否在列表中,而不是对象本身。
if i.name not in lits: lits.append(i.name)
标签: python python-3.x class attributes