Использование setattr () в python - PullRequest
54 голосов
/ 05 марта 2012

Я ищу кого-то, чтобы объяснить основы того, как использовать, а не использовать setattr().

Моя проблема возникла при попытке использовать один метод / функцию класса для возврата данных, которые затем помещаются в другойметод / функция.Возможно, более простой подход был бы намного лучше в этом случае, но я пытаюсь понять, как работают / используются классы.Эта проблема, похоже, связана с setattr(), и это моя попытка использовать ее довольно просто.

Хотя это не совсем та же проблема, я следовал Python The Hard Way, ex42 - while loop @ lines 18-41.

Я пытался написать\__init__(), и вместо этого использовал getattr(), думая, что, возможно, что-то должно быть в пространстве имен класса, но это, похоже, не помогает.

#! /bin/python2.6

class HolyGrail(object):

    def __init__(self):
        self.start = 'start_at_init'

    # function definition in question:
    # TypeError: 'str' object is not callable

    def run_it(self):
        start = setattr(self, 'name', 'get_thing')
        start = self.name

        # Something wrong here?
        value_returned = start() #I believe this == self.get_thing()
        use_it(value_returned)

    """
    # alternate function definitions
    # NameError: global name 'start' is not defined

    def __init__(self):
        self.start = 'get_thing'

    def run_it(self):
        go_do_it = getattr(self, start)
        first_output = go_do_it()
        use_it(first_output)
    """

    def get_thing(self):
        return "The Knights Who Say ... Ni!"

    def use_it(self, x):
        print x
        print "We want a shrubbery!"

my_instance = HolyGrail()
my_instance.run_it()

@ Карл Кнехтель, @Эмбер, @ Крис Морган, спасибо за вашу помощь.

Думаю, теперь я могу объяснить свой ответ!Это потребовало лучшего понимания себя как объекта для меня.Это имя экземпляра, которое помечается такими вещами, как атрибуты.

Класс может быть Town, а затем.getattr ищет дом, используя его имя, так что вы скоро можете его вызвать, и находит другое место, если вы не можете найти дом - С getattr существует «имя», и вы идетеНайди это.Делает переход от одной функции к другой динамически. В качестве бонуса у вас может быть значение по умолчанию, полезное для получения запасного метода по умолчанию - соединение оборвалось или что-то?

setattr строит дом и дает ему имятак что вы можете позвонить об этом позже.Вы можете потенциально отстроить этот дом или пойти в конкретное место, если вы не можете его найти.- setattr создает имя атрибута и задает или изменяет его значение для последующего вызова Возможно, пользователь отключит звук, тогда будущие методы не будут выводить звук.

Я мог бы написать свойфункционируют несколькими способами, но нет необходимости изменять какие-либо атрибуты:

def run_it(self):
    yo = getattr(self, 'get_thing')
    answer = yo()
    setattr(self, 'deal_accepted', self.use_it) #really ott
    no = getattr(self, 'deal_accepted')
    no(answer)

Правильно исправленный код:

def run_it(self):
    value_returned = self.get_thing()
    self.use_it(value_returned)

Ответы [ 5 ]

73 голосов
/ 05 марта 2012

Документы Python говорят все, что нужно сказать, насколько я вижу.

setattr ( объект , имя , значение )

Это аналог getattr(). Аргументами являются объект, строка и произвольное значение. Строка может называть существующий атрибут или новый атрибут. Функция присваивает значение атрибуту, если объект позволяет это. Например, setattr(x, 'foobar', 123) эквивалентно x.foobar = 123.

Если этого недостаточно, объясните, что вы не понимаете.

63 голосов
/ 05 марта 2012

Вы устанавливаете self.name в строку "get_thing", а не функцию get_thing.

Если вы хотите, чтобы self.name была функцией, вы должны установить ее на одну:

setattr(self, 'name', self.get_thing)

Однако для вашего другого кода это совершенно не нужно, потому что вы можете просто вызвать его напрямую:

value_returned = self.get_thing()
11 голосов
/ 08 марта 2017

SetAttr: Мы используем setattr , чтобы добавить атрибут к нашему экземпляру класса. Мы передаем экземпляр класса, имя атрибута и значение. и с getattr мы получаем эти значения

Например

Employee = type("Employee", (object,), dict())

employee = Employee()

# Set salary to 1000
setattr(employee,"salary", 1000 )

# Get the Salary
value = getattr(employee, "salary")

print(value)
4 голосов
/ 26 августа 2017

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

class Example:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
0 голосов
/ 20 мая 2019

Чтобы добавить к другим ответам, типичный случай использования, который я нашел для setattr(), - это использование конфигов.Распространено разбирать конфиги из файла (.ini-файла или чего-либо еще) в словарь.Таким образом, вы получите что-то вроде:

configs = {'memory': 2.5, 'colour': 'red', 'charge': 0, ... }

Если вы хотите назначить эти конфиги для класса, который будет храниться и передаваться, вы можете сделать простое назначение:

MyClass.memory = configs['memory']
MyClass.colour = configs['colour']
MyClass.charge = configs['charge']
...

Тем не менее, гораздо проще и менее многословно перебирать конфиги, и setattr() примерно так:

for name, val in configs.items():
    setattr(MyClass, name, val)

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

* Обратите внимание, что ключи dict должны быть строками, поскольку они будут именами объектов класса.

...