Предположим, у меня есть класс с конструктором (или другой функцией), который принимает переменное количество аргументов и затем условно устанавливает их как атрибуты класса.
Я мог бы установить их вручную, но кажется, что параметры переменных достаточно распространены в python, и для этого должна быть общая идиома. Но я не уверен, как это сделать динамически.
У меня есть пример с использованием eval, но это вряд ли безопасно. Я хочу знать, как это сделать - может быть, с помощью лямбды?
class Foo:
def setAllManually(self, a=None, b=None, c=None):
if a!=None:
self.a = a
if b!=None:
self.b = b
if c!=None:
self.c = c
def setAllWithEval(self, **kwargs):
for key in **kwargs:
if kwargs[param] != None
eval("self." + key + "=" + kwargs[param])
pip install attrs
украсьте свой класс@attr.s
и установите аргументы какa = attr.ib(); b = attr.ib()
и т. д. Подробнее здесь .Ответы:
Вы можете обновить
__dict__
атрибут (который представляет атрибуты класса в форме словаря) с помощью ключевого слова arguments:тогда ты можешь:
и примерно так:
вы можете предварительно отфильтровать ключи (используйте
iteritems
вместо этого,items
если вы все еще используете Python 2.x).источник
self.__dict__.update(locals())
для копирования также позиционные аргументы.kwargs[0]
а не простоkwargs
? Можетkwargs
вообще целочисленный ключ? Я почти уверен, что это должны быть струны.Вы можете использовать
setattr()
метод:Есть аналогичный
getattr()
метод получения атрибутов.источник
.getattr()
? Или вы можете получить доступ к атрибутам с помощьюFoo.key
?Foo.attrname
. Думаю, я просто указывал на то, чтоgetattr
метод существует. Это также полезно, если вы хотите указать значение по умолчанию, когда именованный атрибут недоступен.Большинство ответов здесь не охватывают хороший способ инициализировать все разрешенные атрибуты только одним значением по умолчанию. Итак, чтобы добавить к ответам @fqxp и @mmj :
источник
False
. Хорошая точка зрения!Я предлагаю вариант ответа fqxp , который, помимо разрешенных атрибутов , позволяет вам устанавливать значения по умолчанию для атрибутов:
Это код Python 3.x, для Python 2.x вам потребуется хотя бы одна корректировка
iteritems()
вместоitems()
.источник
Еще один вариант, основанный на отличных ответах mmj и fqxp . Что если мы хотим
Под «напрямую» я подразумеваю избегание постороннего
default_attributes
словаря.Не большой прорыв, но может кому-то пригодится ...
РЕДАКТИРОВАТЬ: если наш класс использует
@property
декораторы для инкапсуляции «защищенных» атрибутов с помощью методов получения и установки, и если мы хотим иметь возможность устанавливать эти свойства с помощью нашего конструктора, мы можем захотеть расширитьallowed_keys
список значениями изdir(self)
, как показано ниже:Приведенный выше код исключает
dir()
(исключение при наличии "__"), иdir()
, имя которого не находится в конце имени атрибута (защищенного или иного) from__dict__.keys()
, таким образом, вероятно, сохраняются только методы, украшенные @property.Это изменение, вероятно, действительно только для Python 3 и выше.
источник
Я вызвал этот класс,
SymbolDict
потому что это, по сути, словарь, работающий с использованием символов вместо строк. Другими словами, вы делаетеx.foo
вместо этого,x['foo']
но под одеялом на самом деле происходит то же самое.источник
Следующие решения
vars(self).update(kwargs)
илиself.__dict__.update(**kwargs)
не являются надежными, поскольку пользователь может войти в любой словарь без сообщений об ошибках. Если мне нужно проверить, что пользователь вставил следующую подпись ('a1', 'a2', 'a3', 'a4', 'a5'), решение не сработает. Более того, пользователь должен иметь возможность использовать объект, передав «позиционные параметры» или «параметры пары значений и значений».Поэтому я предлагаю следующее решение с использованием метакласса.
источник
Возможно, это лучшее решение, но мне на ум приходит следующее:
источник
это самый простой через ларск
мой пример:
источник
kwargs
- словарь аргументов ключевого слова иitems()
метод, возвращающий копию списка(key, value)
пар словаря .Я подозреваю, что в большинстве случаев может быть лучше использовать именованные аргументы (для лучшего самодокументирования кода), чтобы он мог выглядеть примерно так:
источник
for key, value in (a, b, c)