Practical guidelines for beautiful Python code | TurnKey GNU/Linux
You are here
Category: All
Practical guidelines for beautiful Python code
Blog Tags:
development
python
insight
design
methodology
Practical guidelines for beautiful Python code
Alon Swartz
- Mon, 2011/01/10 - 12:32 -
3 comments
Every now and then Liraz and I find ourselves chatting about how much we love Python, but more so the lessons we have learned from coding, and how to apply them to create beautiful Python code. I've tried to refine some of the "lessons" into practical guidelines that I apply religiously to all new code I write, and the refactoring of old code I written.
When reading other peoples code it sometimes ties my mind into knots, and on occasions I want to pull my hair out in frustration and disgust.  That's not to say I'm perfect, but hopefully these guidelines will benefit others (and indirectly help reduce my hair loss).
I couldn't possibly include everything I wanted to in one post, so this will be the first, and more will follow...
#1 - OO structure == Well defined mental concepts
Object Orientated structure should always map to well defined mental concepts in the problem domain. If you don't have a well defined mental model of the problem domain, start with that.
Class Responsibility Collaboration (CRC)
cards are really useful in this.
Basically you need a sketch of the architecture. What parts does your system have, what are their names, what does each part do? What parts is that part made out of? How do the parts interact with each other?
You can save quite a bit of effort if you come up with a good architecture up-front, but sometimes it may be easier to start without and figure it out a bit later after you have a bit more knowledge about the problem you are solving.
The rule is that the sooner you refine your architecture, the better. It is easy to dig yourself further and further into a complexity hole that makes restructuring very difficult later on. So do that as early as possible.
Refining the architecture is part of the "refactor mercilessly" rule.
#2 - Leverage built-in Python types
It is often a good idea to build on top of built-in Python types or at least emulate them.
The big advantage in building on top of Python's conventions is that you get to re-use Python's abstractions instead of reinventing your own.  Python is famous for its minimal elegance, and the language designers take great care making small beautiful data structures. Making your code structures more Pythonic is a pretty good way to leverage the built-in elegance of the language while saving yourself quite a bit of work (inventing good abstractions is hard!).
If you've never inherited from a built-in data type, experiment with a small test case in a throw away script. This way you don't mangle your current project and you can be as experimental as you like.
Tip: Construction can be a bit trickier than a normal object if your initialization interface is different from the built-in type. In that case you'll need to override the __new__ magic method as well to call the __new__ constructor of the base class with different arguments than your __new__ is called.
For example:
class IntField(int):
def __new__(cls, val, name):
return int.__new__(cls, val)

def __init__(self, val, name):
self.name = name
self.val = val

int.__init__(self, val)
As for emulating built in types, Python provides magical method names for emulating any built-in behavior. See
special method names
for reference.
#3 - Use the class namespace, Luke!
Use the class namespace when defining class-level attributes and the instance namespace (which inherits from the class namespace on initialization) when defining instance level attributes.
For example, constants are always class level attributes because they are shared by all instances. On a practical level there are two reasons to do this:
Enable inheritance
- you can't override instance level attributes, only class level attributes.
Readability
- code is communication. Setting an attribute at the class level or instance level is making a statement about the nature of that attribute, which makes the code easier to read and understand.
#4 - staticmethod vs. classmethod vs. regular method
Static methods
are simpler and more readable than class methods because they don't have access to the class attribute, so it's easier to determine its input (i.e., arguments), and output (i.e., the return value).
Class methods
are simpler than regular methods because the convention is that you don't usually manipulate attributes in the class namespace the way you would manipulate attributes in the instance namespace. So when you call a class method you know its not going to be sneaking around behind you back reading or writing to any instance level attributes set by other methods. The input for a class method is therefore the arguments it receives + class level constants. Its output is the return value.
A regular method
is the most complex and easy to abuse type of method.  Its harder for the programmer to see what the inputs for the method are, and what its output is.
Lets consider the following case: imagine a class in which all private methods are called without arguments and do not return output values.  Instead, the private methods freely read and write to any attributes in
self
The problem with such a pattern, is that all methods have now become entangled in a
spaghetti like dependency structure
. The instance namespace in effect behaves like a global namespace and it becomes very difficult to understand methods in terms of input and output.  Furthermore, the boundaries between methods can easily become fuzzy and unclear.
You must never ever do this (I have in the past, and I'm ashamed). If your code exhibits this pattern, go fix it, now!
Private methods have input arguments and return values for a reason. The instance namespace must only be used for instance level attributes which need to persist after a public method has been called.
Until it becomes second nature, these rules should help:
If a method doesn't need access to instance level attributes
then
it should be a class method, not a regular method.
If a method doesn't need access to class level attributes
then
it should be a static method, not a class method.
The Python Paradox
Paul Graham wrote an interesting essay entitled The
Python Paradox
. It's a quick read - take a look.
Comments
I hope
Adrian Moya
- Mon, 2011/01/10 - 15:57
this doesn't mean you took a look at my tkldevenv-webapp code :P LOL. Anyway, when you do: remember is my first time with the python/django tools. I'll be expecting your feedback on that one.
reply
Oh no, I wasn't referring to your code...
Alon Swartz
- Mon, 2011/01/10 - 16:14
I haven't had the chance to take a look at tkldevenv yet. I'm closing up loose ends so we can finalize the 11.0 release. Once I do that I can come up for air.
I also owe you feedback on the tklpatches, haven't forgot about that.
reply
speaking of python
bmullan
- Tue, 2011/01/11 - 00:58
I recently found
Jono Bacon's Acire project/tool for Python code "snippets"
contributions.
The tool itself is pretty useful as a repository of python modules you accumulate.
reply
Pages
Add new comment
Apps
Specials
Web development
Framework
Stack
IT Infrastructure
Content management
Blogging
Ecommerce
Education
Wiki
Media
Business management
CRM
ERP
Invoicing
Messaging
Email
Forum
Chat
Issue tracking
Project management
Database
NoSQL
Developer tools
Help
Forums
Support
General
Development
Documentation
Security and News Announcements
Low-traffic newsletter: up to one email a month.
Previous issues
Categories
development
news
appliances
community
debian
release
hub
stable
iso
security
cloud
ec2
aws
proxmox
lxc
ubuntu
tkldev
tips
v16.x
drupal
More tags
Recent posts
Free up disk space
4th Aug, 2024
Python PEP 668 - working with "externally managed environment"
29th Jul, 2024
v18.0 Stable Release #6 - 10 Newly Updated ISOs, Hub Builds & Proxmox/LXC builds
17th Apr, 2024
v18.0 Stable Release #5 - 20 Updated ISOs & Hub Builds - Proxmox/LXC builds
12th Feb, 2024
v18.0 Stable Release #4 - 10 Updated ISOs & Hub Builds - Proxmox/LXC builds
5th Feb, 2024
1 of 63
next ›
Archive
August 2024
(1)
July 2024
(1)
April 2024
(1)
February 2024
(2)
November 2023
(1)
October 2023
(1)
September 2023
(1)
July 2023
(1)
April 2023
(1)
March 2023
(1)
December 2022
(1)
November 2022
(2)
Pages
Recent comments
V19?
TurnKey LXC templates are available via the Proxmox UI
Non-Aws platforms
Thanks for that!
the command for adding the
mtoolshub
Great post