Как спорить поиск на питоне: make.up.a.dot.separated.name.and.use.it.until.destroyed = 777 - PullRequest
5 голосов
/ 21 октября 2009

Я новичок в Python с очень специфическим зудом, чтобы экспериментировать с процессом поиска точек имени в Python. Как мне кодировать класс или функцию в «make.py», чтобы эти операторы присваивания работали успешно?

import make

make.a.dot.separated.name = 666
make.something.else.up = 123
make.anything.i.want = 777

1 Ответ

15 голосов
/ 21 октября 2009
#!/usr/bin/env python

class Make:
    def __getattr__(self, name):
        self.__dict__[name] = Make()
        return self.__dict__[name]

make = Make()

make.a.dot.separated.name = 666
make.anything.i.want = 777

print make.a.dot.separated.name
print make.anything.i.want

Специальный метод __getattr__ вызывается, когда именованное значение не найдено. Строка make.anything.i.want в итоге делает эквивалент:

m1 = make.anything    # calls make.__getattr__("anything")
m2 = m1.i             # calls m1.__getattr__("i")
m2.want = 777

Приведенная выше реализация использует эти вызовы __getattr__ для создания цепочки из Make объектов каждый раз при обращении к неизвестному свойству. Это позволяет произвольно углублять точечные доступы до окончательного присвоения, в котором назначается реальное значение.

Документация Python - настройка доступа к атрибутам :

object.__getattr__(self, name)

Вызывается, когда поиск атрибута не обнаружил атрибут в обычных местах (то есть он не является атрибутом экземпляра и не найден в дереве классов для self). name - имя атрибута. Этот метод должен вернуть (вычисленное) значение атрибута или вызвать исключение AttributeError.

Обратите внимание, что если атрибут найден с помощью обычного механизма, __getattr__() не вызывается. (Это намеренная асимметрия между __getattr__() и __setattr__().) Это делается как из соображений эффективности, так и в противном случае __getattr__() не будет иметь доступа к другим атрибутам экземпляра. Обратите внимание, что по крайней мере для переменных экземпляра вы можете подделать тотальный контроль, не вставляя никаких значений в словарь атрибутов экземпляра (вместо этого вставляя их в другой объект). См. Метод __getattribute__() ниже, чтобы узнать, как на самом деле получить полный контроль в классах нового стиля.

object.__setattr__(self, name, value)

Вызывается при попытке присвоения атрибута. Это вызывается вместо обычного механизма (то есть сохраните значение в словаре экземпляра). name - это имя атрибута, value - это значение, которое будет присвоено ему.

Если __setattr__() хочет присвоить атрибуту экземпляра, он не должен просто выполнять self.name = value - это вызовет рекурсивный вызов самого себя. Вместо этого он должен вставить значение в словарь атрибутов экземпляра, например, self.__dict__[name] = value. Для классов нового стиля вместо доступа к словарю экземпляров следует вызывать метод базового класса с тем же именем, например, object.__setattr__(self, name, value).

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