Какой питонный / более быстрый способ проверить, является ли аргумент «key» пользовательского метода __getitem__ слайсом? - PullRequest
4 голосов
/ 19 мая 2011

У меня есть пользовательский тип последовательности.По сути, это оболочка для списка плюс логический флаг, и я хотел, чтобы он эмулировал обычное поведение неизменяемой последовательности.

Моя проблема связана с нарезкой.Я понимаю, что в Python 3 способ его реализации состоит в том, чтобы иметь метод __getitem__(key), который возвращает элемент, если %key представляет собой одиночный индекс, и секционированную последовательность, если %key является объектом среза.Но как мне различать эти случаи?

У меня есть две гипотезы.

sliced_list = self.wrapped_list[key]
if isinstance(key, slice):
    return MyCustomSequenceType(sliced_list, boolean_flag)
return sliced_list

Но это зло, не правда ли?Или

sliced_list = self.wrapped_list[key]
try:
    return MyCustomSequenceType(sliced_list, boolean_flag)
except TypeError:
    return sliced_list

Последний выглядит более питоническим.Он опирается на тот факт, что MyCustomSequenceType.__init__(self, datas, flag) вызывает len (данные), поэтому он поднимает TypeError, если %datas является integer.Но тогда, если __init__ поднимает TypeError для другой случайной проблемы, она не будет отслеживаться.Также http://wiki.cython.org/enhancements/numpy/getitem намекает на то, что isinstance быстрее (на самом деле его легче оптимизировать).

Что мне тогда делать?

Ответы [ 2 ]

4 голосов
/ 19 мая 2011

Вы можете просмотреть стандартную библиотеку и скопировать, что там делается. Например, calendar.py имеет:

def __getitem__(self, i):
    funcs = self._months[i]
    if isinstance(i, slice):
        return [f(self.format) for f in funcs]
    else:
        return funcs(self.format)

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

2 голосов
/ 19 мая 2011

Это должно быть isinstance(key, slice), а не isinstance(key, "slice").

Кроме того, вам не следует звонить __getitem__ напрямую - используйте обозначение элемента [].

Для себя я бы использовал бы метод isinstance(key, slice), если бы мне нужно было различить - slice - это особенная вещь, а не то, что легко можно заменить другим типом (подумайте - если self.wrapped_list является list, slice является единственным типом объекта, который будет возвращать не элемент или ошибку).

Так что я бы закончил так:

sliced_list = self.wrapped_list[key]
if isinstance(key, slice):
    return MyCustomSequenceType(sliced_list, boolean_flag)
return sliced_list

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

...