2017-02-09 4 views
2

В рамках крупного проекта в Python3, мне нужен метод в духе следующего (не работает) Код:питона: присвоить значение атрибута по имени

class Qclass: 
    def __init__(self, a, b, c): 
     self.a = a 
     self.b = b 
     self.c = c 

def increment(Q, var): 
    eval('Q.{} = Q.{} + 100'.format(var,var)) 

Q = Qclass(1,2,3) 
increment(Q,'a') 
print(Q.a) 
>>> 101 

мне это нужно, потому что я не» t иметь предварительные знания, по которым должен быть увеличен атрибут Q. Решение было бы объявить конкретные функции для каждого атрибута и использовать какой-то селектор, но я предпочел бы избежать этого, если это возможно.

Есть ли опрятный способ сделать это?

+0

Возможный дубликат [Как вы программно установить атрибут в Python] (http://stackoverflow.com/questions/285061/how-do-you- programatically-set-an-attribute-in-python) –

ответ

3

Это очень плохая идея в использование eval(..) (практически в любом контексте). Вы можете использовать getattr(..) и setattr(..), которые являются более безопасными:

def increment(Q, var): 
    setattr(Q,var,getattr(Q,var)+100) 

getattr(obj,name) и setattr(obj,name,val) получить и установить атрибут obj ЭСТ. Таким образом, вы можете получить/установить атрибут, если вы не знаете имя заранее.

Так полученный код:

class Qclass: 
    def __init__(self, a, b, c): 
     self.a = a 
     self.b = b 
     self.c = c 

def increment(Q, var): 
    setattr(Q,var,getattr(Q,var)+100) 

Q = Qclass(1,2,3) 
increment(Q,'a') 
print(Q.a) 
+0

arrr, да! Я полностью забыл о setattr() getattr(). Благодарю. Хотя вы отредактировали мой вопрос, чтобы поместить def increment() в Qclass? Я имел в виду, что это должно быть у корня. – Aderam

+0

@Aderam: а это не так? Было что-то не так с отступом, потому что '__init__' был в том же отступе, что и' class' ... –

+0

oups, извините за опечатку. Теперь все верно, как и должно быть :) – Aderam

0

Сочетание setattr и getattr бы:

def increment(Q, var): 
    setattr(Q, var, getattr(Q, var) + 100) 

получая 101 для Q.a после того как ваш фрагмент кода выполняется.

getattr просто захватывает атрибут объекта по заданному имени (и допускает использование по умолчанию, если атрибут не существует); аналогично Q.<val_name>.

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

0

Вы можете использовать встроенную функцию vars, которая возвращает словарь переменных, объявленных в заданной области. Это использование выглядит следующим образом:

Q = Qclass(1,2,3) 
try: 
    vars(Q)['a'] += 1 
except KeyError: 
    Q.a = 1 
+0

Изначальный подход, не знал о vars(). Для записи я сравнил это решение с setattr (Q, var, getattr (Q, var) + 1). Кажется, они очень близки к равным с точки зрения вычислительного времени. Спасибо – Aderam

+0

Этот подход работает только с классами, которые имеют '__dict__', для классов без (например, с помощью' __slots__') это не работает. Это эквивалент использования 'Q .__ dict __ ['a'] + = 1' – mata

Смежные вопросы