[英]Is there any implementation of Python2 where ordering is transitive?
每個主流Python實現都以某種方式失敗,除了Skulpt,但它可以說是一個不完整的實現。
CPython(和變體),PyPy和Jython :
>>> 'b' < () < u'ab' < 'b'
True
IronPython :
IronPython在內部比較不同對象的.NET Object.GetHashCode()
哈希值,因此您可以通過濫用int
和float
比較的特殊處理以及float('+inf')
的內部哈希表示小於[]
的哈希(我不確定這是多么穩定,所以它可能不適用於IronPython的每次安裝):
>>> 2**200 < float('+inf') < [] < 2**200
True
>>> {1: 3} < {1: 4} < {1: 3}
1
>>> {1: 3} < {1: 3}
0
Skulpt
如果將Skulpt視為Python 2的完整實現(它無法比較字典和其他一些不方便的類型,並且沒有unicode
類型),它實際上可以通過復制CPython的規則進行比較並方便地省略unicode
類型:
# 1. None is less than anything
# 2. Sequence types are greater than numeric types
# 3. [d]ict < [l]ist < [s]tring < [t]uple
>>> None < 0 < {} < [] < '' < ()
True
對於CPython 2,你實際上有[t]uple < [u]nicode
,但由於unicode
和str
比較是作為特殊情況處理的,你會失去傳遞性。 雖然Python 2不太可能獲得補丁來修復這個“錯誤”,但我認為你可以通過明確地改變以下順序來確保傳遞性:
[d]ict < [l]ist < [s]tring < [t]uple < [u]nicode
至:
[u]nicode < [d]ict < [l]ist < [s]tring < [t]uple
這樣, str
對unicode
比較的特殊情況不會破壞任何東西。
一些比較聲明為 Python 2.7中未指定 :
最重要的比較一般規則在“Python語言參考”第5章中。表達式/ 5.9 比較 。
第一個規則是眾所周知的用於比較數字類型(bool,int,long,float),字符串(str,unicode),元組和列表的規則。 最后兩條規則聲明了未指定的內容:
- 當且僅當它們的排序(鍵,值)列表比較相等時,映射(字典)才相等。 [5]除了平等以外的結果一致地得到解決,但沒有另外定義 。 [6]
- 內置類型的大多數其他對象比較不相等,除非它們是同一個對象; 一個對象被認為是小於還是大於另一個對象的選擇是在程序的一次執行中任意但一致地做出的。
許多特定規則在上面引用的Python標准庫 / 內置類型的 比較章節中,以及關於復雜 , 十進制或分數等特定類型的文檔中。
類型complex不支持順序比較,它應該引發TypeError。 十進制類型按值進行比較。 它與自從Python 2.7以來的numbers.Number兼容。 fractions.Fraction也按值進行比較。
我的反思:如果比較關系可以是任意的,並且在同一台計算機上的程序的兩次執行中不可重現,那么說傳遞性是沒有用的。 上面在Python 2中明確指定順序的所有情況都應該在Python 3中引發TypeError。
Python 2.7中已知的內置類型的傳遞性或排序僅在實現不同內置類型的值的等效性但未實現等效於其他類型的類型之間。
示例: IronPython中的傳遞性受損(受Blender評論的啟發並簡化):
>>> assert long(0) < 1.0 < [] < long(0) # 0 < 1; 'float' < 'list' < 'long'
即使是看起來更簡單的等效性( ==
) 也不總是可傳遞的。 這打破了操作員的傳遞性( <=
)。 請參閱注釋中的示例。 (感謝您的解決方案)(等效性不是身份.a a is b
意味着a == b
,但反之亦然。)
示例使用許多普通的用戶定義類,名稱為單字母大寫或小寫:
class A(object): pass
class a(object): pass
...
class z(object): pass
所有數字類型在CPython和IronPython中都有許多自然等價的值(可能在所有其他實現的文檔中)
>>> assert (False == 0 == 0L == 0.0 == 0 + 0j == Decimal('0') == Fraction(0, 1) <
... True == 1 == 1L == 1.0 == 1 + 0j == Decimal('1') == Fraction(1, 1))
數字類型在CPython中的所有其他類型之前排序:
>>> assert 0 < 10**1000 < float('inf') < A() < Z() < a()
數值類型分散在IronPython中的其他類型之間
>>> assert D() < decimal.Decimal('0') < E()
>>> assert F() < fractions.Fraction(0, 1) < G()
>>> assert b() < False < c() # bool
>>> assert c() < 0 + 0j < d() # complex
>>> assert f() < 0.0 < g() # float
>>> assert i() < 0 < j() # int
>>> assert l() < 0L < m() # long
str,bytearray和unicode具有等效值
>>> assert bytearray('ab') == 'ab' == u'ab'
CPython中使用了對其他類型的訂購沒有什么特別之處,
>>> assert b() < bytearray('ab') < c() # bytearray
>>> assert s() < 'ab' < t() # str
>>> assert u() < u'ab' < v() # unicode in CPython
在IronPython中:類型unicode
行為類似於str
。 這並不奇怪,因為字符串在.NET中像unicode一樣實現,而且在IronPython中也是如此。
>>> assert s() < u'ab' < t() # unicode in Iron Python like str
>>> unicode
<type 'str'>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.