Reputation: 163
Currently this is what I'm doing:
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
but honestly that's quite tedious and makes adding any more facultative attributes a real pain.
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?
EDIT: apparently this works perfectly:
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))
that is, just setting all defaults values then overriding them with the keyword args using for element in kwargs: setattr(self, element, kwargs[element])
Let me know if there's any cleaner way, though I have to say I'm much more satisfied with this.
Upvotes: 2
Views: 68
Reputation: 160377
To reduce the clutter, you could alternatively define a defaults dictionary attribute _init_attrs
for example, define your function with **kwargs
and then setattr
on self
with a loop, using _init_attrs[k]
as a default
value for kwargs.get
when no parameters were supplied:
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)
This makes __init__
a bit more mystifying but achieves the goal of making it way more extensible while cutting down the size.
Upvotes: 3