Питон простой инт подкласс


Ниже-это класс, предназначенный для реализации Rememember молокос приоритетами задач. Я использую его частично, как упражнение в "подходящие для Python" Программирование, так что это уже довольно проста, но советы о том, как сделать ее проще или более подходящие для Python будут особенно оценены.

Я с помощью Python 2.6.5 в случае, если это делает никакой разницы.

class Pri(int):    # Subclass int to get handy comparison functions etc.
    '''Task priority'''

    public_from_internal = {1: 1, 2: 2, 3: 3, 4: 'N'}
    internal_from_public_str = {'N': 4, '1': 1, '2': 2, '3': 3}
    _dict = dict()

    def __new__(cls, level):
        try:
            level = Pri.internal_from_public_str[str(level)]
        except KeyError:
            raise ValueError, "Pri must be 'N', '1', '2', or '3'"

        # If there's already an instance of this priority, don't create a new one.
        if level in Pri._dict: return Pri._dict[level]
        else: return super(Pri, cls).__new__(cls, level)

    def __init__(self, level):
        super(Pri, self).__init__()
        Pri._dict[self] = self

    def __repr__(self): return "Pri('" + str(Pri.public_from_internal[self]) + "')"

    # Priority 1 is clearly greater than priority 3, so invert cmp
    def __cmp__(self, other): return (-cmp(int(self), int(other)))

Некоторые выход, для любопытных:

>>> Pri(1)
Pri('1')
>>> Pri('N')
Pri('N')
>>> Pri(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "rtm.py", line 10, in __new__
    raise ValueError, "Pri must be 'N', '1', '2', or '3'"
ValueError: Pri must be 'N', '1', '2', or '3'
>>> Pri._dict
{Pri('1'): Pri('1'), Pri('N'): Pri('N')}
>>> Pri(1) > Pri(2)
True
>>> bool(Pri('N'))
True
>>> repr(Pri("2"))
"Pri('2')"
>>> print repr(Pri('N'))
Pri('N')
>>> Pri(1)._dict
{Pri('1'): Pri('1'), Pri('2'): Pri('2'), Pri('N'): Pri('N')}


1604
3
задан 23 ноября 2011 в 06:11 Источник Поделиться
Комментарии
1 ответ

class Pri(int):    # Subclass int to get handy comparison functions etc.

Сокращения слов в названиях классов делает это тяжелее, чтобы следовать. Просто назвать это приоритет

    '''Task priority'''

public_from_internal = {1: 1, 2: 2, 3: 3, 4: 'N'}
internal_from_public_str = {'N': 4, '1': 1, '2': 2, '3': 3}
_dict = dict()

Называя этот _dict не дать мне подсказку о том, что его использовали для

    def __new__(cls, level):
try:
level = Pri.internal_from_public_str[str(level)]

Мне не нравится строкового представления все, что передается здесь. Ты действительно хочешь только, чтобы поддержать строк и целых чисел не то, что происходит, чтобы преобразовать в строки в правильных типов.

        except KeyError:
raise ValueError, "Pri must be 'N', '1', '2', or '3'"

# If there's already an instance of this priority, don't create a new one.
if level in Pri._dict: return Pri._dict[level]
else: return super(Pri, cls).__new__(cls, level)

Использовать следующие вместо того, чтобы построить:

try:
return Pri._dict[level]
except KeyError:
return super(Pri,cls).__new__(cls, level)

Я думаю, что его все яснее, и это будет немного быстрее.

    def __init__(self, level):
super(Pri, self).__init__()
Pri._dict[self] = self

Меня этот __новый__ и нет __инит__ функция.

    def __repr__(self): return "Pri('" + str(Pri.public_from_internal[self]) + "')"

Мне не нравится ввод имени метода и реализация на одной линии. Я думаю, что это заставляет его выглядеть clutered. Я также рекомендую использовать возвращение "При (в%S)" % при.public_from_internal[сам] как я думаю, яснее, как к результату.

    # Priority 1 is clearly greater than priority 3, so invert cmp
def __cmp__(self, other): return (-cmp(int(self), int(other)))

Вы унаследовали от int, чтобы сделать сравнения. Но тогда вам придется переопределить сравнение в любом случае. Теперь у вас также есть все другие вещи, такие как добавление/multipyling/вычитания/и т. д., которые не имеет смысла применять к приоритетам. В принципе, нет никаких причин, чтобы наследовать от int здесь, и много причин этого не делать.

Как бы я сделать это

class Priority(object):
priorities_by_name = {}
@classmethod
def from_string(cls, name):
return cls.priorities_by_name[name]

priorities_by_number = {}
@classmethod
def from_number(cls, number):
return cls.priorities_by_number[number]

def __init__(self, name, number):
self.priorities_by_name[name] = self
self.priorities_by_number[number] = self
self.name = name
self.number = number

def __repr__(self):
return "Priority<%d>" % self.number

def __cmp__(self, other):
return -cmp(self.number, other.number)

Priority.First = Priority('1', 1)
Priority.Second = Priority('2', 2)
Priority.Third = Priority('3', 3)
Priority.None = Priority('N', 4)

Priority.__init__ = None # Prevent any future creations


  1. Я явно вызывать метод класса, чтобы получить приоритет из любой строки или числа. Я не люблю перегружать один конструктор, чтобы взять или.

  2. Для небольшого числа элементов, я предпочитаю создавать их все сразу. Это делает строительство проще

  3. Я могу получить доступ к приоритетным объектам в приоритетных.Во-первых (и т. д.)

Честно говоря, я, вероятно, не будет реализации приоритетного класса, вместо того, чтобы я отслеживать приоритет как int.

3
ответ дан 24 ноября 2011 в 12:11 Источник Поделиться