What is the cleanest way of setting default values for attributes unless provided by the class call?
<p>Currently this is what I'm doing:</p>

<pre><code>class NewShip:
    def __init__(self, position = (0,0), x_velocity = 25, y_velocity = 15, anim_frame = 1, frame1 = "space_ship_1.png", frame2 = "space_ship_2.png", angle = 0, border_size = 900):
        self.position = position
        self.angle = angle
        self.x_velocity = x_velocity #in pixels per frame
        self.y_velocity = y_velocity #in pixels per frame
        self.anim_frame = anim_frame
        self.frame1 = pygame.image.load(frame1).convert_alpha()
        self.frame2 = pygame.image.load(frame2).convert_alpha()
        self.frame1 = pygame.transform.scale(self.frame1, (128,128))
        self.frame2 = pygame.transform.scale(self.frame2, (128,128))
        self.position = DummyObject()
        self.position.x = position[0]
        self.position.y = position[1]
        self.border_size = border_size
</code></pre>

<p>but honestly that's quite tedious and makes adding any more facultative attributes a real pain.</p>

<p>Should I just skip the whole 'letting people declare attributes with keyword arguments' thing and just instantiate objects in a fully default state before changing any of their attributes?</p>

<p>EDIT:
apparently this works perfectly:</p>

<pre><code>class NewShip:
    def __init__(self, **kwargs):
        self.angle = 0
        self.x_velocity = 25 #in pixels per frame
        self.y_velocity = 15 #in pixels per frame
        self.anim_frame = 1
        frame1 = "space_ship_1.png"
        frame2 = "space_ship_2.png"
        self.position = DummyObject()
        self.position.x = 0
        self.position.y = 0
        self.border_size = 900
        for element in kwargs: setattr(self, element, kwargs[element])
        self.frame1 = pygame.image.load(frame1).convert_alpha()
        self.frame2 = pygame.image.load(frame2).convert_alpha()
        self.frame1 = pygame.transform.scale(self.frame1, (128,128))
        self.frame2 = pygame.transform.scale(self.frame2, (128,128))
</code></pre>

<p>that is, just setting all defaults values then overriding them with the keyword args using <code>for element in kwargs: setattr(self, element, kwargs[element])</code></p>

<p>Let me know if there's any cleaner way, though I have to say I'm much more satisfied with this.</p>

<p>To reduce the clutter, you could alternatively define a defaults dictionary attribute <code>_init_attrs</code> for example, define your function with <code>**kwargs</code> and then <code>setattr</code> on <code>self</code> with a loop, using <code>_init_attrs[k]</code> as a <code>default</code> value for <code>kwargs.get</code> when no  parameters were supplied:</p>

<pre><code>class NewShip:
    def __init__(self, **kwargs):
        _init_attrs = {'angle': 0,
             'anim_frame': 1,
             'border_size': 900,
             'frame1': 'space_ship_1.png',
             'frame2': 'space_ship_2.png',
             'position': (0, 0),
             'x_velocity': 25,
             'y_velocity': 15 }

        for k, v in _init_attrs.items():
            setattr(self, k, kwargs.get(k, v)
</code></pre>

<p>This makes <code>__init__</code> a bit more mystifying but achieves the goal of making it way more extensible while cutting down the size.</p>

python python-3.x