Есть ли ярлык для `self.somevariable = somevariable` в конструкторе класса Python?
Конструкторы в Python часто выглядят так:
class SomeClass:
def __init__(self, a, b = None, c = defC):
self.a = a
self.b = b or []
self.c = c
Есть ли ярлык для этого, например. просто определить __init__(self,**kwargs)
и использовать ключи как свойства self
?
Ответы
Ответ 1
Одна проблема с
self.__dict__.update(locals())
заключается в том, что он включает self
, поэтому вы получаете self.self
. Было бы лучше отфильтровать self
из locals()
например.
vars(self).update((k,v) for k,v in vars().items() if k != 'self')
Вы можете защитить от случайных методов перезаписи с помощью этого варианта
vars(self).update((k,v) for k,v in vars().items()
if k != 'self' and k not in vars(self))
Если вы не хотите, чтобы он терпел неудачу, вы также можете проверить заранее, как это сделать
if any(k in vars(self) for k in vars()):
raise blahblah
vars(self).update((k,v) for k,v in vars().items() if k != 'self')
Ответ 2
Одна идиома, которую я видел, это self.__dict__.update(locals())
. Если вы запустите его в начале метода, это будет обновлять словарь объектов с помощью аргументов (так как это единственные локали в начале метода). Если вы пройдете **kwargs
, вы можете сделать self.__dict__.update(**kwargs)
.
Конечно, это хрупкий подход. Это может привести к загадочным ошибкам, если вы случайно передадите аргумент, который маскирует существующий атрибут. Например, если ваш класс имеет метод .doSomething()
, и вы случайно передаете конструктор doSomething=1
, он переопределит этот метод и позже вызовет ошибку, если вы попытаетесь вызвать этот метод. По этой причине лучше не делать этого, кроме как в некоторых тривиальных случаях (например, какой-то прокси-объект, единственная цель которого состоит в том, чтобы служить "сумкой", содержащей несколько атрибутов).
Ответ 3
Да:
class SomeClass:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)