Skip to content

Latest commit

 

History

History
106 lines (77 loc) · 9.83 KB

File metadata and controls

106 lines (77 loc) · 9.83 KB
title
Python / Data Type

Python / Data Type

Equality

  • object.eq(self, other) - 3. Data model — Python 3.7.1 documentation

    • __lt__()__le__()__eq__()__ne__()__gt____ge__() 統稱為 "rich comparison methods",很直覺分別對應 <<===!=>>=;例如 x != y 背後會呼叫 x.__ne__(y)
    • A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given PAIR OF ARGUMENTS (例如 __eq__(self, other) 就是比較 selfother). By convention, False and True are returned for a SUCCESSFUL COMPARISON. 雖然可以回傳其他值,在 boolean context 時會透過 bool() 分出 true/false。例如 if a > b: 可以想成 if bool(a.__gt__(b)):
    • By default, __ne__() delegates to __eq__() and inverts the result unless it is NotImplemented. 也就是只要實作 __eq__() 即可,不過 Python 2 還是得實作 __ne__()
    • See the paragraph on __hash__() for some important notes on creating hashable objects which support custom comparison operations and are usable as dictionary keys. => 自訂 hashable 的 comparison 時,要注意
    • There are no swapped-argument versions of these methods ... ??
  • object.eq(self, other) - 3. Data model — Python 2.7.15 documentation #ril

    • There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected.

None

Python 中的 None 等同於其他語言的 null,不過它是個 object,型態是 types.NoneType

import types

def test_none_singleton():
    assert isinstance(None, types.NoneType)

按照 Programming Recommendations - PEP 8 -- Style Guide for Python Code | Python.org 的說法:

Comparisons to singletons like None should always be done with is or is not, never the equality operators.

由於 None 是 singleton,比對時要用 is/is not (identity),如果用 ==/!= (equality) 可能會受到 operator overloading 的影響:

class Negator(object):

    def __eq__(self, other):
        return not other # doesn't make sense

    def __ne__(self, other): # requried for py2
        return not self.__eq__(other)

def test_none_identity__use_is():
    none = None
    thing = Negator()

    assert none is None # singleton
    assert thing is not None

def test_none_equality__donot_use_equality():
    none = None
    thing = Negator()

    assert none == None
    assert not (none != None)

    # weird? the result dependes on thing.__eq__()
    assert thing == None
    assert not (thing != None)

參考資料:

Hashable, hash(), hash(), PYTHONHASHSEED ??

  • hashable - Glossary — Python 3.7.1rc1 documentation
    • 明確定義了 An object is hashable if it has a hash value which NEVER CHANGES DURING ITS LIFETIME (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value. 也就是 hash value 相同不一定 equal,但 equal 的一定有相同的 hash value。
    • Hashable 表示可以做為 dictionary key 或是 set member,因為這些資料結構內部會用到 hash value。
    • All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. 明確指出所有的 immutable built-in object 都是 hashable,但 mutable container 都不是。
    • 所有 user-defined class 雖然都是 hashable,但它的 hash value 都是來是 id(),所以不同 instance 一定是 unequal。
  • hash(object) - Built-in Functions — Python 3.7.1rc1 documentation
    • 取得 object 的 hash value (integer);實驗發現,非 hashable 會丟出 TypeError,例如 hash({}) 會丟出 TypeError: unhashable type: 'dict'
    • Numeric values that compare equal have the same hash value (even if they are of different types, as is the case for 1 and 1.0). 這還滿有趣的,大概是 numeric type 的 __hash__() 有特別考量到數值本身。
    • For objects with custom __hash__() methods, note that hash() TRUNCATES the return value based on the bit width of the host machine. 為什麼要這麼做? 不過好像也沒差,hash 本來就不是唯一值。
  • object.hash(self) - 3. Data model — Python 3.7.1rc1 documentation #ril
    • Called by built-in function hash() and for operations on members of hashed collections including set, frozenset, and dict. 看起來 hashed collections 內部並不是透過 hash() 取得 hash value,而是直接調用 __hash__()?
    • 實作上的要求很簡單,只有 "objects which compare equal have the same hash value",提到 mix together the hash values of the components of the object that also play a part in comparison of objects by PACKING THEM INTO A TUPLE AND HASHING THE TUPLE,這招還滿直觀的,例如 return hash((self.name, self.nick, self.color));因為透過 tuple 拿 hash value 的關係,也已經是被 truncate 後的版本了。
    • 接下來有一大串實作 __hash__() 要注意的地方 XD #ril

New-style Class ??

Bound & Unbound ??

super() ??