Распаковка аргумента и присвоение переменным класса
Привет у меня есть следующий код, который пытается создать экземпляр класса и присвоить ему значения аргумента. Я пытаюсь использовать *args, чтобы сделать это следующим образом:
def main():
testdata = ['FDR', False, 4, 1933]
apresident = President(testdata)
print apresident
print apresident.alive
class President:
id_iter = itertools.count(1)
#def __init__(self, president, alive, terms, firstelected):
def __init__(self, *args):
self.id = self.id_iter.next()
self.president = args[0]
self.alive = args[1]
self.terms = args[2]
self.firstelected = args[3]
Я получаю ошибку "Индекс кортежа вне диапазона". Как вы можете видеть из закомментированной строки, я ранее использовал позиционные аргументы для достижения этой цели (что сработало) и использовал для этого строки, подобные следующей:
self.president = president
Как правильно использовать *args в этом случае? я должен использовать *kwargs?
3 ответа
Вы передаете только один аргумент President()
, который является списком
['FDR', False, 4, 1933]
Если вы хотите передать элементы в этом списке как отдельные аргументы, вы делаете это следующим образом:
apresident = President(*testdata) # note the * character
Как указывает полковник Паник, в вашем примере использование распаковки аргументов немного бессмысленно - вероятно, ваш фактический вариант использования более сложен и оправдывает его использование.
ОБНОВЛЕНИЕ:
Ваш комментарий на самом деле является дополнительным вопросом, который будет лучше в качестве отдельного вопроса, но:
def main():
testdata = {
"president": "FDR",
"alive": False,
"terms": 4,
"firstelected": 1933,
}
apresident = President(**testdata)
anotherpresident = President(president="BHO", terms=2, firstelected=2008)
print apresident
print apresident.alive
print anotherpresident
print anotherpresident.alive
class President:
id_iter = itertools.count(1)
#def __init__(self, president, alive, terms, firstelected):
def __init__(self, **kwargs):
self.id = self.id_iter.next()
self.president = kwargs.get("president", None)
self.alive = kwargs.get("alive", True)
self.terms = kwargs.get("president", 1)
self.firstelected = kwargs.get("president", None)
Это показывает, как вы можете определить значения по умолчанию.
Вы должны использовать только *args
если вы не знаете, сколько аргументов будет передано функции.
В вашем случае, похоже, вам нужно все president, alive, terms, firstelected
, Нет ничего плохого в том, чтобы иметь конструктор, который принимает все это в качестве параметров.
*kwargs
используется по нескольким причинам. Один из них - если у вас есть значения по умолчанию, которые следует использовать, если пользователь не хочет их указывать.
Для получения дополнительной информации см. Этот вопрос, этот вопрос и официальную документацию.
В ответ на ваш комментарий
Я бы порекомендовал вам иметь datedied
собственность для каждого президента. Если они еще не умерли, то значение должно быть None
, Когда вы расширяете только определенные экземпляры с помощью функциональности, становится сложнее (но не невозможно) рассуждать о коде.
Сказав это, если вы хотите, чтобы для каждого президента были произвольные свойства, которые явно не будут применимы к каждому экземпляру, то вы можете использовать ключевые аргументы. Но добавление свойств не ограничивается конструктором. Я бы просто использовал setattr() и getattr ().
Как установить свойства класса с помощью kwargs
class President(object):
def __init__(self, *args, **kwargs):
for name, value in kwargs.items():
# Make each keyword-argument a property of the class.
setattr(self, name, value)
tVar = President(is_cool=True)
print tVar.is_cool # Returns True
Ты звонишь President(testdata)
, когда ты должен делать President(*testdata)
для того, чтобы распаковать список, как вы вызываете конструктор.
Прямо сейчас вы по сути передаете один аргумент (список), следовательно, IndexError
: вы передаете один аргумент, так args
равно [testdata]
и не testdata
,
Как уже упоминалось в другом ответе, это не очень Python для использования *args
в вашем конструкторе здесь. Вы знаете, какие аргументы вы ожидаете, так что просто используйте их.
Впрочем, можно использовать его при вызове функции.