2011-03-13 150 views
1

我知道,當我比較兩個物體lhs == rhs兩者定義__eq__,只是lhs.__eq__被稱爲除非它返回NotImplementedrhslhs一個子類。欺騙Python的運算符優先級

但是我想實現一個類,在與任意對象進行比較時,它們的實例將有機會說出他們想說的內容,而不管arbitrary_object.__eq__的實現細節以及比較語句中的位置如何。聽起來有些尷尬,但我正在開發一個面向測試的項目,看看testmania.expect,你就會明白我需要的是什麼。

我最初的想法是讓我的課是使用元類魔法和__instancecheck____subclasscheck__任何其他類的子類。但他們根本不會在簡單比較的情況下被調用。

有人有什麼新鮮的想法嗎?

回答

1

我不知道這是否適合您的需要,但爲什麼不測試這兩個操作,我的意思是測試如果:object1 == object2object2 == 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() 

希望這可以幫助。

+0

感謝您的回答。那麼,始終保持期望值是一個解決方案,但它打破了習慣:許多人習慣於寫'some_assert(what_i_have,what_i_want_to_have)'。改變這只是爲了期望逆轉不是好主意imho。 – nkrkv 2011-03-13 21:45:33

+0

@nailxx:也許我在答案中不夠清楚:)你可以在doctest中看到,你可以在函數assert_equal的第一個或第二個參數中傳遞期望對象,它會起作用,因爲我'先執行==第二或第二個第一個',那麼你將首先執行'first .__ eq __(second)',如果它不是True,你將執行'second .__ eq __(first)',如果對象的第一個或第二個是'__eq__'記者將運行的期望:) – mouad 2011-03-13 22:34:22

+0

嗯,好吧,你要重新實現'assert_equal'本身。 Uff,替換標準的'TestCase.assertEqual'有點奇怪。但也許這是正確的方向。 – nkrkv 2011-03-14 09:29:24