【问题标题】:combining bitwise inverse with bitwise or将按位求逆与按位或相结合
【发布时间】:2019-09-26 20:57:16
【问题描述】:

给定以下类:

import operator
class Foo(object):
    def __init__(self, bah):
        self.bah = bah      

    def __invert__(self):
        return {'not': self.bah}

    def __repr__(self):
        return self.bah

    def __or__(self, other):
        return {'or': [self.bah, other]}    


x = Foo('obj1')
y = Foo('obj2')

我能做到:

operator.inv(x) # ~x

这给了我:

{'not': 'obj1'}

我能做到:

operator.or_(x, ~y) # x | ~y

这给了我:

{'or': ['obj1', {'not': 'obj2'}]}

但为什么我做不到:

operator.or_(~x, y) # ~x | y

这会引发以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-175-92fdd35dc3b3> in <module>
----> 1 operator.or_(~x, y)

TypeError: unsupported operand type(s) for |: 'dict' and 'Foo'

我怎样才能输出以下内容?

{'or': [{'not': 'obj1'}, 'obj2']}

【问题讨论】:

  • 您的运算符应该返回Foo 的实例,以便您可以在它们上调用更多运算符。
  • or 运算符从左侧计算其操作数。 ~x 首先被评估,然后or 被应用。由于~x 从您在Foo 类中的定义中返回dict,因此or 将应用于dict 和未定义的Foo。参考:docs.python.org/3/reference/expressions.html#or

标签: python bitwise-operators operator-keyword bitwise-or


【解决方案1】:

在这种情况下,您需要重载 __ror__。有关 Python 如何评估运算符的详细信息,请参阅this post

基本上就是这样的说法

operator.__or__(~x, y)

相同
x.__invert__().__or__(y)

由于没有为x.__invert__() 返回的dict 对象定义__or__,因此调用失败。定义 __ror__ 将使 Python 解释器尝试评估

y.__ror__(x.__invert__())

第一次尝试失败后的~x | y

【讨论】:

  • 谢谢!这很棒! __ror__ 作为反向或。这输出 {'or': ['obj2', {'not': 'obj1'}]} 很好
  • 嗯,operator.__or__(~x, ~y) 呢?我也会考虑这个。但它给了我TypeError: unsupported operand type(s) for |: 'dict' and 'dict'
  • 好吧,如果需要支持,那么 __or____ror__ 不应返回 dict 对象。它们应该返回 Foo 对象或其他支持 or 操作的对象。
  • 你是对的。将尝试找出让{'or': [{'not': 'obj1'}, {'not':'obj2'}]} 也能正常工作
【解决方案2】:

似乎operator.or_() 调用会查找您提供的first 参数中定义的__or__ 方法。这就是为什么在 operator.or_(x, ~y) 的情况下它可以正常工作 - x 是包含 __or__ 的 Foo 对象。定义。

在第二种情况下,operator.or_(~x, y),然而,~x 的输出是一个字典 {'not': 'obj1'},它不包含 __or__ 定义。

【讨论】:

    【解决方案3】:

    根据我应该返回 Foo 实例的 cmets 提供另一个答案

    class Foo(object):
        def __init__(self, name):
            self.name = name      
    
        def __invert__(self):
            return Foo({'not': self.name})
    
        def __repr__(self):
            return str(self.name)
    
        def __or__(self, other):
            return Foo({'or': [self.name, other]})
    
        def __and__(self, other):
            return Foo({'and': [self.name, other]})   
    
    
    x = Foo('obj1')
    y = Foo('obj2')
    

    有了这个我可以做到:

    >>> operator.or_(~x, y) # ~x | y
    {'or': [{'not': 'obj1'}, 'obj2']}
    

    甚至

    >>> operator.or_(~x, ~y) # ~x | ~y
    {'or': [{'not': 'obj1'}, {'not': 'obj2'}]}
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 1970-01-01
      相关资源
      最近更新 更多