Writing Python in a “Pythonic” way means adhering to conventions1 and using the language in the most general way possible2. I would even go so far and say, that only Pythonic code is correct code. Unfortunately, this assumption crumbles away when using Python code to interact with an end-user.
It is not uncommon to use Python itself as a domain specific language because it is easy to learn and comes with a high quality, standard library and a vast amount of third-party libraries that fill in even the smallest niche. This was also the route that a colleague and I took for a piece of software that we are currently developing. With this software, the user is expected to control hardware devices from within an IPython shell.
Here is the dilemma: On the one hand, I try to write as Pythonic as possible, on
the other hand, I want to make it as easy as possible for the user to accomplish
a given task. For example, in a proper way, a function is called by appending
parentheses at the end of the name. But then, is the user aware of being inside
a programming environment? Instead of writing
device.show_info(), the user
wants to type
and investigate a device’s state. So, I abuse
__repr__ and return a string
that does not “look like a valid Python expression”, hence violating a very
basic requirements of the object “protocol”. Not very cool in my book.
I also added a function that shows information for all devices currently
defined. This is impossible to achieve without inspecting the frame stack,
iterating over all
globals() and checking the type via
isinstance(). This is
pure magic, but again very helpful for the user.
Without going on with more examples, the question quickly becomes: Where to draw the line? How much should I mess with Python internals for the sake of a nice user interface? Is even using Python as a DSL the right approach?
Maybe I am not experienced enough, but unfortunately I cannot answer these questions.