Форум сайта python.su
def delegate(attribute_name, method_names): def decorator(cls): nonlocal attribute_name if attribute_name.startswith("__"): attribute_name = "_" + cls.__name__ + attribute_name for name in method_names: setattr(cls, name, eval("lambda self, *a, **kw: " "self.{0}.{1}(*a, **kw)".format( attribute_name, name))) return cls return decorator _identity = lambda x: x @delegate("__list", ("pop", "__delitem__", "__getitem__", "__iter__", "__reversed__", "__len__", "__str__")) class SortedList(object): def __init__(self, sequence=None, key=None): self.__key = key or _identity # __key хранит ссылку на функцию # более длинный, но более логичный аналог инструкции вверху: # self.__key = key if key is not None else _identity assert hasattr(self.__key, "__call__") # убеждаемся, что эту функу можно вызывать if sequence is None: self.__list = [] elif (isinstance(sequence, SortedList) and # проверка является заданная последовательность объектом типа SortedList sequence.key == self.__key): # и не используется ли длдя этой последовательности та же самая ключевая функция self.__list = sequence.__list[:] # если оба удовлетворяют, то создается поверхностная копия последовательности без сортировки else: self.__list = sorted(list(sequence), key=self.__key) @property # предотвращаем изменение key def key(self): return self.__key # метод двоичного поиска или метод половинного деления def __bisect_left(self, value): key = self.__key(value) left, right = 0, len(self.__list) while left < right: middle = (left + right) // 2 if self.__key(self.__list[middle]) < key: left = middle + 1 else: right = middle return left def add(self, value): index = self.__bisect_left(value) if index == len(self.__list): self.__list.append(value) else: self.__list.insert(index, value) def remove(self, value): index = self.__bisect_left(value) if index < len(self.__list) and self.__list[index] == value: del self.__list[index] else: raise ValueError("{0}.remove(x): x not in list".format( self._class__.__name__)) def remove_every(self, value): count = 0 index = self.__bisect_left(value) while(index < len(self.__list) and self.__list[index] == value): del self.__list[index] count += 1 return count def count(self, value): count = 0 index = self.__bisect_left(value) while(index < len(self.__list) and self.__list[index] == value): del self.__list[index] index += 1 count += 1 return count def index(self, value): index = self.__bisect_left(value) if index < len(self.__list) and self.__list[index] == value: return index raise ValueError("{0}.index(x): x not in list".format( self.__class__.__name__)) def __delitem__(self, index): del self.__list[index] def __getitem__(self, index): return self.__list[index] def __setitem__(self, index): raise TypeError("use add() to insert a value and rely on " "the list to put it in the right place") # этот метод используется для поддержки синтаксиса for value in iterable # Обратите внимание: когда объект интерпретируется как # последовательность, то используется именно этот метод. Так, чтобы # преобразовать объект L типа SortedList в простой список, можно вызвать # функцию list (О, в результате чего интерпретатор Python вызовет метод # SortedList. iter (/.), чтобы получить последовательность, # необходимую функции list(). def iter(self): return iter(self.__list) # Этот метод обеспечивает поддержку встроенной функции reversed(), # благодаря чему мы можем записать, например, for value in reversed(iterable). def __reversed__(self): return reversed(self.__list) # Метод contains () обеспечивает поддержку оператора in. И снова # мы можем использовать быстрый алгоритм двоичного поиска вместо # медленного алгоритма линейного поиска, используемого классом list. def __contains__(self, value): index = self.__bisect_left(value) return (index < len(self.__list) and self.__list[index] == value) # Метод SortedList. pop() удаляет элемент из указанной позиции и возвращает # его или возбуждает исключение IndexError, если индекс находится за пределами # списка. def clear(self): self.__list = [] # В методах рор(), len () и st г () мы просто перекладываем работу на объект self. # list. Метод SortedList.clear() отбрасывает существующий список и замещает его # новым пустым списком. def pop(self, index=-1): return self.__list, pop(index) def __len__(self): return len(self.__list) def __str__(self): return str(self.__list) def copy(self): return SortedList(self, self.__key) # Теоретически высокая скорость копирования таким способом недостижима # для функции сору.соруО, однако мы легко можем исправить этот # недостаток, добавив строку: # сору = сору # Когда вызывается функция сору. сору(), она сначала пытается # использовать специальный метод сору () объекта и только в случае его # отсутствия выполняет свой собственный программный код. Благодаря # этой строке функция сору.соруО теперь сможет при работе с # отсортированными списками использовать метод SortedList. сору(). (То же # самое возможно в случае реализации специального метода deepco- # ру (), но это немного сложнее - электронная документация модуля # сору содержит все необходимые подробности.) __copy__ = copy letters = SortedList(("H", "c", "B", "G", "e"), str.lower) print str(letters) letters.add("G") letters.add("f") letters.add("A") print str(letters) print letters[2] # Press ENTER or type command to continue # ['B', 'c', 'e', 'G', 'H'] # ['A', 'B', 'c', 'e', 'f', 'G', 'G', 'H'] # c
Отредактировано remoshka (Дек. 23, 2014 16:45:25)
Офлайн
103
nonlocal появилась в 3 пайтоне!
Офлайн