гетерогенные сравнения в python3 - PullRequest
0 голосов
/ 05 мая 2010

Я на 99 +% все еще использую Python 2.x, но я стараюсь думать о том дне, когда я переключусь.

Итак, я знаю, что использование операторов сравнения (меньше / больше или равно) в гетерогенных типах, которые не имеют естественного упорядочения, больше не поддерживается в python3.x - вместо некоторых непротиворечивых (но произвольных) результат мы вместо этого поднимаем TypeError. Я вижу в этом логику, и даже в основном считаю, что это хорошо. Последовательность и отказ от догадок - это добродетель.

Но что, если вы по сути хотите поведение python2.x? Какой лучший способ получить его?

Ради интереса (более или менее) я недавно внедрил Skip List , структуру данных, которая сохраняет свои элементы отсортированными. Я хотел использовать гетерогенные типы в качестве ключей в структуре данных, и мне нужно сравнивать ключи друг с другом, пока я прохожу структуру данных. Способ сравнения python2.x делает это действительно удобным - вы получаете понятное упорядочение среди элементов, которые имеют естественное упорядочение, и некоторые упорядочение среди тех, которые этого не делают.

Последовательное использование ключа сортировки / сравнения, такого как (type(obj).__name__, obj), имеет недостаток, заключающийся в том, что он не чередует объекты, которые имеют естественное упорядочение; все ваши float сгруппированы вместе до того, как ваши int с, а ваш str полученный класс отделяется от ваших str с.

Я придумал следующее:

import operator

def hetero_sort_key(obj):
    cls = type(obj)
    return (cls.__name__+'_'+cls.__module__, obj)

def make_hetero_comparitor(fn):
    def comparator(a, b):
        try:
            return fn(a, b)
        except TypeError:
            return fn(hetero_sort_key(a), hetero_sort_key(b))
    return comparator

hetero_lt = make_hetero_comparitor(operator.lt)
hetero_gt = make_hetero_comparitor(operator.gt)
hetero_le = make_hetero_comparitor(operator.le)
hetero_ge = make_hetero_comparitor(operator.gt)

Есть ли лучший способ?

Я подозреваю, что можно было бы построить угловой случай, который бы это испортил - ситуация, когда вы можете сравнить тип A с B и тип A с C, но где B и C повышают TypeError по сравнению, и вы можете закончить с чем-то нелогичным, как a > b, a < c, и все же b > c (из-за того, как сортируются их имена классов). Я не знаю, насколько вероятно, что вы столкнетесь с этим на практике.

1 Ответ

0 голосов
/ 05 мая 2010

Вместо того, чтобы "исправлять" что-то, что сообщество python 3.x "исправило" в глобальной области видимости, вы можете попробовать подход, позволяющий вашим объектам / типам правильно сортироваться. Я не так хорошо знаком с Python 3.x, но я уверен, что все еще есть метод __cmp__, который можно переопределить в подклассе и исправить, чтобы сравнения работали. Вы можете использовать это в сочетании с id() для восстановления старого испорченного поведения (которое просто сортируется по позиции в памяти, id(), если моя память мне правильно служит).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...