Распаковка аргумента и присвоение переменным класса

Привет у меня есть следующий код, который пытается создать экземпляр класса и присвоить ему значения аргумента. Я пытаюсь использовать *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 в вашем конструкторе здесь. Вы знаете, какие аргументы вы ожидаете, так что просто используйте их.

Впрочем, можно использовать его при вызове функции.

Другие вопросы по тегам