Подмена приоритета оператора Python - PullRequest
1 голос
/ 13 марта 2011

Я знаю, что когда я сравниваю два объекта lhs == rhs и оба определяют __eq__, вызывается просто lhs.__eq__, если только он не возвращает NotImplemented или rhs не является подклассом lhs.

Однако я хотел бы реализовать класс, экземпляры которого при сравнении с произвольными объектами получат возможность сказать то, что они хотят сказать, независимо от деталей реализации arbitrary_object.__eq__ и независимо от положения в операторе сравнения.Это звучит немного неловко, но я работаю над небольшим проектом, ориентированным на тестирование, взгляните на testmania.expect, и вы поймете, для чего мне это нужно.

Моя первоначальная идея состояла в том, чтобы сделать мой класс подклассом любого другого класса, используя магию метаклассов и __instancecheck__, __subclasscheck__.Но их просто не вызывают в случае простого сравнения.

Есть ли у кого-нибудь свежие идеи?

1 Ответ

1 голос
/ 13 марта 2011

Я не знаю, будет ли это соответствовать вашим потребностям, но почему бы не проверить две операции под этим, я имею в виду проверить, если: object1 == object2 и object2 == object1, и обычно вы должны получить одно и то же значение, если только один изобъект перезаписал метод __eq__, поэтому вы выполните этот новый метод __eq__ и вернете тот, который является истинным, пример лучше слов:

def _assert_just_now(first, second):
    """A Dump function to simulate if two dates are almost equal.

    N.B: In this Dump function i will just test if the two datetime object have the
    same hour

    """ 

    from datetime import datetime
    assert isinstance(first, datetime) and isinstance(second, datetime), \
           "This function only accept datetime objects"

    return first.hour == second.hour

class Expectation(object):

     def __init__(self, assertion, first):
         self.assertion = assertion
         self.first = first

     def __eq__(self, other):
         return self.assertion(self.first, other)

def assert_equal(first, second):
   """Usage :

   >>> from datetime import datetime
   >>> t1 = datetime(year=2007, hour=1, month=3, day=12)
   >>> t2 = datetime(year=2011, hour=1, month=5, day=12)

   Without using Expectation it's False.
   >>> assert_equal(t1, t2)
   False

   Use the Expectation object.
   >>> assert_equal(t1, Expectation(_assert_just_now, t2))
   True

   Can use Expectation in the first argument too.
   >>> assert_equal(Expectation(_assert_just_now, t2), t1)
   True

   Work also in Container object.
   >>> assert_equal({'a': 1, 'b': Expectation(_assert_just_now, t2)},
   ...              {'a': 1, 'b': t1})
   True

   We change a little bit the values to make the assert equal fail.
   >>> t3 = datetime(year=2011, hour=2, month=5, day=12)
   >>> assert_equal(t1, t3)
   False

   This just to make sure that the _assert_just_now doesn't accept object 
   other than datetime:
   >>> assert_equal(t1, Expectation(_assert_just_now, "str"))
   Traceback (most recent call last):
       ...
   AssertionError: This function only accept datetime objects

   """

   return first == second or second == first

if __name__ == '__main__':
   import doctest
   doctest.testmod() 

Надеюсь, это поможет.

...