Как динамически генерировать атрибуты? - PullRequest
0 голосов
/ 13 октября 2018

Я использовал приведенный ниже код Python:

class A(object):
   def __getattr__(self, name):
       print "__getattr__ : %s" % name
       setattr(self, name, A())
       print self.__dict__
       print getattr(self, name)

 x = A()
 x.a = 1 .  # Works fine.
 print x.a

 x.b.c = 2 # Throws error.
 print x.b.c

В последней части выдается следующая ошибка:

NoneType object has no attribute c.

Может кто-нибудь объяснить, что это за ошибка в приведенном выше коде, как print self.__dict__ ясно показывает, что и a, и b были вставлены в словарь объекта.

Мой вариант использования состоит в том, чтобы иметь объект, для которого атрибуты могут динамически добавляться по мере необходимости.Как я должен уметь использовать:

x = A()
x.a = 1
x.b.c = 2
x.d.e.f.g = 3

Кроме того, есть ли другой способ достижения моей цели?

Обновление: Обнаружена ошибка, __getattr__ должен вернуть значение.

Правильный код

class A(object):
   def __getattr__(self, name):
       print "__getattr__ : %s" % name
       x = A()
       setattr(self, name, x)
       print self.__dict__
       print getattr(self, name)
       return x # getattr(self, name)

 x = A()
 x.a = 1 .  # Works fine.
 print x.a

 x.b.c = 2 # Works fine.
 print x.b.c

1 Ответ

0 голосов
/ 14 октября 2018

__getattr__ вызывается, когда атрибут запрашивается для получения, но недоступен из запрашиваемого объекта.

Предполагается, что x не имеет a, такой вызов как

result = x.a

функционально эквивалентно

result = getattr(x, "a")

, что функционально эквивалентно

result = type(x).__getattr__(x, "a")

который обычно совпадает с

result = x.__getattr__("a")

Последние два варианта отличаются, только если __getattr__ привязан к объекту вместо класса (, который может не работать )

Как вы можете видеть здесь, __getattr__ должен возвращать значение, которое должно иметь a.

Он также может устанавливать атрибут напрямую, чтобы дальнейшие запросы на получение неВызовите __getattr__ снова, но обрабатываются непосредственно Python.Это зависит от конкретного варианта использования, если это имеет смысл (в вашем случае это имеет смысл).

x.b.c = 2 обычно переводится здесь как-то вроде

setattr(x.__getattr__("b"), "c", 2)

Опять же, __getattr__ должен вернуть здесь объект, для которого установлен атрибут c.

...