Syntax
Takes a bit of time to get used to it but after a certain point it just becomes natural. Like english. No heavy-weight operators or complicated syntax. I can bring a lot of examples but this is not about specific commands this is about the soul of the language.
Yield
I think this is one of the most overlooked function in python. I see so few occurrence and I’m very surprised about this. So when does this really come handy. If you want to write clean code you put different logic in different layers of code which you eventually want to represent. Let’s say we have an MVC framework (Django will do) where you want some logic on the models to happen on the in the model layer and you want to rearrange the result set of a query in a dictionary in the view and represent it in the template. You need three for cycle for this. You go through the list three times unnecessary as all you have to do is instead of return do a yield in the model and controller. Small tuning steps like this can make huge different in the long run.
Instead of
1 2 3 4 5 6 |
_list = [] for _o in ObjectModelsClass.objects.filter(whatever=1).order_by('somecolumn'): _o.dothemagic() _list.append((_o, othervar)) return _list |
You can write this:
1 2 3 |
for _o in ObjectModelsClass.objects.filter(whatever=1).order_by('somecolumn'): _o.dothemagic() yield _o, othervar |
Decorators
Decorators are one of the first subjects pop up when somebody talks about python so I don’t think I need to write novels about how helpful are they. I just simply love their existence and use them in my every day tasks a lot.
Inline statements
Usually it’s a bad practice to try to enforce everything in one line but there are cases when is extremely helpful not to write complex code blocks. I think real life examples tell more than description.
Set the modules for a client based on its subscription bundle.
1 |
self._modules = [ _m.code for _m in self.bundle.modules.all() ] |
Prepare a days dictionary for storing opening hours of a shop.
1 |
_days = dict(((d, None) for d in range(1,8))) |
Distance form field in django with configured choices.
1 |
distance = forms.ChoiceField(choices=[( km, '%i km' % km ) for km in [1,2,5,20,50,100]], initial=5) |
Everything is an object
I saw first time pythoners to have difficulties understand the concept of everything being an object however it comes very handy in many times. Again let’s see an example what I made as a nagios check_nrpe command:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class check_numeric(object): def __init__(self, critical, warning): self.critical = critical self.warning = warning def __call__(self, fn): def check(*args, **kwargs): number, msg = fn(*args, **kwargs) if number > self.critical: return 2, 'CRITICAL', msg elif number > self.warning: return 1, 'WARNING', msg else: return 0, 'OK', msg return check |
This is a decorator which can have parameters at initialization. What it does is converting a simple function which returns a number and a message to a check_nrpe command.
1 2 3 |
@check_numeric(critical=86400, warning=43200) # This return an instance of check_numeric class with the defined properties. def latest_backup(): return 156700, 'Last backup was done 156700 seconds ago' |
The reason why this can work relies in the fact that everything is an object. Functions are objects, classes are objects. When the decorator is added to the latest_backup function what actually happens is the check_numeric class got initialized with critical and warning parameters and return an object which has the __call__ method defined to modify the behavior of the fn function in the parameter list.
Recent comments