Max
Max

Reputation: 8045

more convenient way to assign variables to class object properties

assign set of variables to class object,usually is this:

player.x = 1
player.y = 10
player.name = 'John'

since list and tuple allow you doing this

a,b,c = (1,10,'John')

so this works

player.x,player.y,player.name = (1,10,'John')

or this

player.x,player.y,player.name = 1,10,'John'

I would like to change player properties, I need to type too much player. Is the a more lazy way to do this?

Upvotes: 0

Views: 151

Answers (7)

Jon Clements
Jon Clements

Reputation: 142126

I'm not 100% sure, but it sounds to me that in this instance, using a namedtuple would be a better approach: the caveat being that only known fields should be present (ie, can't be dynamically added/removed) and the class isn't really anything more than a record with attribute style access to fields.

from collections import namedtuple

Player = namedtuple('Player', 'x y name')
player = Player._make([1, 3, 'Bob'])
print player
# Player(x=1, y=3, name='Bob')
player = player._replace(name='Jim', x=13)
print player
# Player(x=13, y=3, name='Jim')

Otherwise, I would personally go for the adding a convenience method to your Player class.

Upvotes: 0

Pierre GM
Pierre GM

Reputation: 20339

A basic loop could work:

for (k,v) in zip(attribute_names, attributes_values):
    setattr(player, k, v)

Of course, you could sue some list comprehension, like:

trash = [setattr(player, k, v) for (k,v) in zip(attribute_names, attributes_values)]

but it doesn't really improve anything (your trash holds as many None as len(attribute_names)...

Upvotes: 1

Lauritz V. Thaulow
Lauritz V. Thaulow

Reputation: 50985

Here's another way of doing this, but like all the others, it's less readable than what you started with:

from functools import partial

map(partial(setattr, player), ("x", "y", "name"), (1, 10, 'John'))

If you set the same set or sets of attributes several places in your code, perhaps adding a well-named method for each such set is a better option?

class Player(object):

    # [...]

    def set_stats(self, x, y, name):
        self.x = x
        self.y = y
        self.name = name

Then you can set these attributes using code that is both short and very readable:

player.set_stats(1, 10, "John")

Upvotes: 1

grc
grc

Reputation: 23545

What about something like this:

def set_properties(instance, properties):
    for property in properties:
        setattr(instance, property, properties[property])

Since we are talking about a lazy programmer you could rewrite the function as:

def set_properties(instance, properties):
    for key,val in properties.iteritems():
        setattr(instance, key, val)

The above code is a bit shorter, but should also run faster for large dictionaries, because it is unpacked once before the loop. Compare to the first version where there properties dictionary is called every iteration.

Usage:

set_properties(player, {'x': 1, 'y': 10, 'name': 'John'})

Upvotes: 2

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250891

using zip() and player.__dict__:

In [14]: class player:
   ....:     pass
   ....: 

In [15]: for prop,value in zip(("x","y","name"),(1,10,"john")):
    player.__dict__[prop]=value
   ....:     
   ....:     

In [18]: player.__dict__
Out[18]: {'__doc__': None, '__module__': '__main__', 'name': 'john', 'x': 1, 'y': 10}

Upvotes: 1

Omnikrys
Omnikrys

Reputation: 2558

player.__dict__.update({'x':12,'y':24,'name':'Billy'})

Not shorter but using dictionaries can be handy in more instances than just a direct example like you provided.

Upvotes: 2

Pratik Mandrekar
Pratik Mandrekar

Reputation: 9568

You could use a method to wrap together changes to properties you might find always happen together like def edit(self, **kwargs) or just positional args and assign self.property = kwargs.get(propertyName, default) on the player class within this. You can also create a property on the class that does the tuple assignment of the kind you have used in the example.

Upvotes: 0

Related Questions