#python
#python
Вопрос:
Я пытался создать класс, который может присваивать несколько атрибутов разным значениям за один раз. Итак, я попытался изменить setattr для этого.
class hello():
def __setattr__(self,attr,value):
if type(attr) == str:
self.__dict__[attr] = value
elif type(attr) == list:
for item,val in zip(attr,value):
self.__dict__[item] = val
else:
print "Error!!!"
чтобы мой желаемый класс имел свойство:
>>> hola = hello()
>>> setattr(hola,["a","b"],[1,2])
>>> hola.a
1
>>> hola.b
2
Но выполнение этого возвращает
TypeError: attribute name must be string, not 'list'
Это правда, что я могу определить специальный метод внутри класса для этой работы, например
def assigner(self, attrlist, valuelist):
for item,value in zip(attrlist,valuelist):
self.__dict__[item] = value
Но хотелось бы знать, почему это невозможно с помощью setattr и наиболее эффективного способа выполнения этой работы
Комментарии:
1.
if type(attr) == str:
вы не должны делать это для проверки типов. Используйтеisinstance
вместо этого:if isinstance(attr, str):
. Также обратите внимание: вместо того, чтобы устанавливать атрибуты один за другим в__dict__
, вы могли бы сделать :self.__dict__.update(zip(attrlist, valuelist))
. Это более эффективно, чем делать это вручную.
Ответ №1:
Из документации по setattr
функции:
Аргументами являются объект, строка и произвольное значение.
Второй аргумент должен быть str
.
Возможным обходным путем является определение __setitem__
вместо __setattr__
class hello():
def __setitem__(self, k, v):
self.__dict__.update(zip(k, v) if type(k) is tuple else [(k, v)])
Это позволит вам присваивать значения в dict
стиле
In [2]: heya = hello()
In [3]: heya['a', 'b'] = [1, 2]
In [4]: heya.a
Out[4]: 1
In [5]: heya.b
Out[5]: 2
Тем не менее, ничто не мешает вам назначать их так
In [15]: heya.a, heya.b = [1, 2]
Ответ №2:
Ну TypeError
, это довольно хорошо сказано: имя (второй аргумент) должно быть строкой, а не списком.
Аргументами являются объект, строка и произвольное значение