Как создать атрибуты экземпляра, перебирая аргументы __init__?

Мне было интересно, есть ли способ генерировать атрибуты класса, перебирая аргументы метода init без явного обращения к списку, содержащему все аргументы метода init?

В приведенном ниже примере я могу перебрать hp, image, speed, x, y, чтобы создать собственные аргументы?

class Character(pygame.sprite.Sprite):
    def __init__(self, hp, image, speed, x, y):

        # Call the parent class (Sprite) constructor
        super(Character, self).__init__()

        self.image = image
        self.rect = self.image.get_rect().move(x, y) #initial placement
        self.speed = speed
        self.hp = hp

Например, с циклом, который будет выглядеть так:

class Character(pygame.sprite.Sprite):
    def __init__(self, hp, image, speed, x, y):

        # Call the parent class (Sprite) constructor
        super(Character, self).__init__()

        for arg in arguments:
             self.arg = arg

Я не совсем уверен, как заставить «аргументы» относиться к hp, image, speed, x и y? Или я застрял в использовании списка, как показано ниже?

class Character(pygame.sprite.Sprite):
    def __init__(self, hp, image, speed, x, y):

        # Call the parent class (Sprite) constructor
        super(Character, self).__init__()

        for arg in [self, hp, image, speed, x, y]:
             self.arg = arg

person Sorade    schedule 29.04.2016    source источник
comment
for arg in [self, hp, image, speed, x, y]: self.arg = arg просто оставит вас с одним атрибутом arg со значением y ....   -  person schwobaseggl    schedule 29.04.2016
comment
@Sorade был ли ответ полезным (если да, пожалуйста, примите)? Вы решили свою проблему (пожалуйста, сообщите другим людям, как вы это сделали)?   -  person salomonderossi    schedule 29.04.2016


Ответы (2)


Вы можете использовать ключевое слово аргументы (kwargs) и определите список атрибутов, которые требуются вашим экземплярам и, следовательно, вы ожидаете в своем __init__(). Затем вы можете просмотреть их и назначить свои атрибуты через setattr:

class Character(pygame.sprite.Sprite):
    ATTRS = ('hp', 'image', 'speed', 'x', 'y')

    def __init__(self, **kwargs):
        # Call the parent class (Sprite) constructor
        super(Character, self).__init__()
        for attr in self.ATTRS:
            setattr(self, attr, kwargs.get(attr))  # sets to None if missing
        set_rect(...)  # do your processing of x, y

Или, что еще проще, просто превратить все kwargs в атрибуты экземпляра:

class Character(pygame.sprite.Sprite):
    def __init__(self, **kwargs):
        super(Character, self).__init__()
        for key, value in kwargs.items():
            setattr(self, key, value)

Однако я бы посоветовал вам воздержаться от такого обмана. Это может сделать ваш __init__ короче, но позже это снизит вашу производительность, так как большинство функций завершения/разрешения кода IDE (Eclipse-PyDev, PyCharm и т. д.) не обнаружат такие динамически устанавливаемые атрибуты в существующих экземплярах, а также не предложат требуемые аргументы. при вызове конструктора, что особенно раздражает других кодеров, использующих ваш класс.

Это также не делает ваш код более читабельным. Представьте, что вы наследуете кодовую базу, в которой используется множество таких конструкций. Вы научитесь любить чистую явную версию, подобную первой, которую вы предлагаете в своем вопросе. Компромисс для сокращения вашего конструктора будет использовать множественное назначение

self.image, self.speed, self.hp = image, speed, hp
self.rect = self.image.get_rect().move(x, y)
person schwobaseggl    schedule 29.04.2016

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

class Test(object):
    def __init__(self, *args):
        for arg in args:
            print(arg)

t = Test("one", 2, "three")
person salomonderossi    schedule 29.04.2016
comment
Но вы не можете назначать их полям своего экземпляра таким образом. - person Byte Commander; 29.04.2016
comment
Ты прав. Ответ от @schwobaseggl решает эту проблему;) - person salomonderossi; 29.04.2016