Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 21, 2014 12:43:57

remoshka
Зарегистрирован: 2014-10-11
Сообщения: 44
Репутация: +  0  -
Профиль  

[resolved] декоратор класса(опять неработающий пример из книги)

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

nonlocal attribute_name
error| invalid syntax

Отредактировано remoshka (Дек. 23, 2014 16:45:25)

Офлайн

#2 Дек. 21, 2014 22:44:51

terabayt
От: Киев
Зарегистрирован: 2011-11-26
Сообщения: 1099
Репутация: +  103  -
Профиль   Отправить e-mail  

[resolved] декоратор класса(опять неработающий пример из книги)

nonlocal появилась в 3 пайтоне!



————————————————
-*- Simple is better than complex -*-

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version