Friday 26 December 2014

Python built-in: setattr(), getattr()

setattr(object, name, value)


setattr() sets a named attribute on an object. The arguments are an object, a string and an arbitrary value.
setattr(x, 'foobar', 123) is equivalent to x.foobar = 123.

Example Usage:

Lets assume Peter's mother has to write a class for preparing tiffin box for her son Peter who does not want to eat very regularly. Everyday in a week she puts random sandwichs and fruits in the tiffin box and checks if peter has eaten that or not. Let help her write the class using setattr()

class TiffinBox(object):
    def __init__(self):
        setattr(self, random.choice(['bacon', 'egg', 'jam']),
             random.choice(range(1, 4)))
        setattr(self, random.choice(['bacon', 'egg', 'jam']), 
             random.choice(range(1, 4)))

Here we are setting a random food with a random number from 1 to 3. The number defines the amount of that food in Peter's tiffin box.
Now we also want Peter to drink something and check if he has eaten the food. Let's write some methods in this class to do those.

class TiffinBox(object):
    def __init__(self):
        setattr(self, random.choice(['apple', 'banana', 'oranges']), 

             random.choice(range(1, 4)))
        setattr(self, random.choice(['bacon', 'egg', 'jam']), 

             random.choice(range(1, 4)))

    def take_drink(self):
        drinks = random.choice(['coffee', 'tea'])
        setattr(self, 'drink', drinks)

    def eat_food(self):
        for food in self.__dict__:
            setattr(self, food, 0)
        setattr(self, 'eaten', True)


Peter can eat using eat_food method and if he eats that food we will add a new attribute to the object named eaten set it to Boolean True and make the all the food count 0 assuming Peter ate all the foods.
We can also add a weekday attribute here. Now the class looks like this.

# -*- coding: utf-8 -*-
import random
from datetime import datetime

class TiffinBox(object):
    def __init__(self):
        setattr(self, random.choice(['apple', 'banana', 'oranges']), random.choice(range(1, 4)))
        setattr(self, random.choice(['bacon', 'egg', 'jam']), random.choice(range(1, 4)))
        self.tiffin_day = self.get_weekday(datetime.now().weekday()) + '_tiffin'
    def __str__(self):
        return self.tiffin_day

    def take_drink(self):
        drinks = random.choice(['coffee', 'tea'])
        setattr(self, 'drink', drinks)

    def get_weekday(self, weekday):
        py_week = {
            0: 'monday', 1: 'tuesday', 2: 'wednesday', 3: 'thursday', 4: 'friday', 5: 'saturday',6: 'sunday' }
        return py_week.get(weekday)

    def eat_food(self):
        for food in self.__dict__:
            setattr(self, food, 0)
        setattr(self, 'eaten', True)

Now Peter's mother can prepare tiffin for him.

>>>tiffin =TiffinBox()
>>>tiffin.__dict__
>>>{'apple': 3, 'jam': 3, 'tiffin_day': 'friday_tiffin'}
>>>tiffin.eat_food() 
>>>tiffin.__dict__
>>>{'eaten': True, 'apple': 0, 'jam': 0, 'tiffin_day': 'friday_tiffin'}

Neat !!

getattr(object, name[, default]) -> value


getattr() is a python built-in that gets a named attribute from an object and return the value of that attribute.
The attribute name must be a string. getattr(x, 'y') is equivalent to x.y. default is an optional argument.
If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

>>>la = range(5)
>>>getattr(la, 'pop') 
<built-in method pop of list object at 0xb7470eac>
>>>la.pop
<built-in method pop of list object at 0xb7470eac>

so getattr(la, 'pop') is equivalent to la.pop. It can be used like a function also.

>>>getattr(la, 'pop')()
4
>>>getattr(la, 'abc')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'abc' 

A  list object has no attribute named 'abc'. So a AttributeError is raised here. But if we use the optional default argument, then the default value is returned.

>>> getattr(la, 'abc', 'no such attribute')
'no such attribute'

Example Usage:

Let's help Peter to find out what his mother has put in the box and in how many amount. He does not know if it's a apple or banana, bacon or jam! Time to use getattr()

mybox = TiffinBox()

for atr in mybox.__dict__:
    print atr, ': ', getattr(mybox, atr)


tiffin_day :  friday_tiffin
bacon :  2
oranges :  3


Hope Peter likes bacons and oranges!




No comments :

Post a Comment