【问题标题】:Problem at Define Class Override (__not__)定义类覆盖的问题 (__not__)
【发布时间】:2020-08-29 18:10:22
【问题描述】:

上下文

作为练习,我正在创建一个Variable 类,目的是表示一个逻辑变量。它被声明为

class Variable(object):
    """ Class for emulate logical variables. """

    def __init__(self, valor, /, name='std var'):

        self.name = name
        if isinstance(valor, bool):
            self.valor = valor
        else:
            raise Exception("Class Error: Constructor must receive a bool as first arg. ")

在这个类中,我重写了一些标准运算符并创建了基本的逻辑函数;如and, or,not

    def truth(self):
        """ Overload de operacion de verdad. """
        return self.valor

    def __eq__(self, other):
        """ Overload del operador =. """
        return True if self.valor == other else False

    def __not__(self):
        """ Overload del operador (not). """
        return True if self.valor else False

    def __and__(self, other):
        """ Overload del operador & (and). """
        return True if (self.valor and other) else False

    def __or__(self, other):
        """ Overload del operador | (or).  """
        return True if (self.valor or other) else False

    def show(self):
        return "{} => {}".format(self.name, self.valor)

问题

最后,我创建了一个测试,该测试引发了一个我无法弄清楚的有趣错误。这是测试代码

def test():
    """ Testing proves. """

    q = Variable(True, 'q')
    p = Variable(False, 'p')
    print("\nDadas {} y {} se da que".format(q.show(), p.show()))

    # Checking __eq__
    assert (q == q) == True
    assert (q == p) == False
    
    # Checking __and__
    assert (q and q) == True
    assert (q and p) == False
    assert (p and p) == False
    # checking __or__
    assert (q  or p) == True
    assert (q  or q) == True
    assert (p  or p) == False
    # checking __not__
    assert (not q) == False
    assert (not p) == True, f'{p.show()=}'

它运行平稳,直到引发下一个错误

assert (not p) == True, f'{p.show()=}'
AssertionError: p.show()='p => False'

我知道引发错误的原因是句子 (not p) == True 是错误的。问题是,为什么?

我的想法和尝试

首先我认为truth 覆盖它不起作用。所以我将p 的所有条目更改为p.valor 并执行

>>> from Module import Variable
>>> 
>>> p = Variable(False)
>>> if p.valor:
>>>     print("Not works")
>>> else:
>>>     print("Or yes")
Or yes

它有效。然后我想到问题可能出在__not__。所以我重写了好几次都没有成功。所以我尝试了这个

>>> p = Variable(True)
>>> # check if its set correctly
>>> print("Y" if p.valor else "N")
Y
>>> # so p.valor its True. Check __not__
>>> not p
False
>>> # here it seems that `__not__` does work, but
>>> p = L.Variable(False)
>>> p.valor
False
>>> print("Y" if p.valor  else "N")
N
>>> not p
False

看起来该功能仅在p.valor = True时才有效...

(编辑)

我……迷路了,但不再迷路了。

DeepSpace的回答之后,我重写了重载函数。所以他们是

    def __bool__(self):
        return self.valor

    def __eq__(self, other):
        return True if self.valor == other else False

    def __not__(self):
        return not(self.valor) 


    def __and__(self, other):
        return True if (self and other) else False

    def __or__(self, other):
        return True if (self or other) else False

有了这个,成功通过了所有的测试

【问题讨论】:

  • 请注意,您应该测试if self.valor == other.valor。您的代码适用于if self.valor == other,因为此比较会触发对other__eq__ 方法的调用,然后将其值与第一个实例的值进行比较——但这有点令人费解,感觉就像你已经很幸运...
  • 另外,请注意,由于同样的问题,assert (p and q) == False 失败了——这次你的测试用例不走运!使用return True if (self.valor and other.valor) else False - 可以简单地写成return self.valor and other.valor

标签: python python-3.x class overriding boolean-logic


【解决方案1】:

__not__ 不是一个神奇的方法,它不是data model 的一部分,它不会被任何东西自动调用。

换句话说,not p 不会调用p.__not__。相反,它只是否定了p.__bool__ 返回的内容。

class Foo:
    def __bool__(self):
        print('In Foo.__bool__')
        return True

print(not Foo())

输出

In Foo.__bool__
False

【讨论】:

  • 谢谢。这解决了问题,现在一切正常。我混淆了truth__bool__ 的定义。
猜你喜欢
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 1970-01-01
  • 2022-06-16
  • 2017-01-02
  • 1970-01-01
相关资源
最近更新 更多