Suggestions for my problems are most welcome.
1. Can't directly bind functions to anything but the current scope.
In python there are three ways to declare a function that I know of and one of them (eval) is sufficiently disgusting to be off the table. The two sane mechanisms are (1) the 'def' syntax which causes a function to be injected into the current scope and (2) the 'lambda' syntax which can't exist over multiple lines, which must return, and where the only way to get side-effects (like output) is via impractical hacks.
Here's something I do quite often:
def process_user_input(cmd):
d_cmd = {}
def cmd_load():
print 'stub for load functionality'
d_cmd['load'] = cmd_load
def cmd_save():
print 'stub for save functionality'
d_cmd['save'] = cmd_save
def cmd_quit():
sys.exit(0)
d_cmd['quit'] = cmd_quit
if cmd not in d_cmd.keys():
print "Command '%s' is unknown."%cmd
else:
d_cmd[cmd]()
That is much nicer than having to declare each function and then have a laborious 'if' statement for each case as well. But this could be much better. Imagine this instead:
def process_user_input(cmd):
d_cmd = {}
d_cmd['load'] = fn(): # 'fn' is a fictional keyword for demonstration
print 'stub for load functionality'
d_cmd['save'] = fn():
print 'stub for save functionality'
d_cmd['quit'] = fn():
print ".. guys ... home .."
sys.exit(0)
if cmd not in d_cmd.keys():
print "Command '%s' is unknown."%cmd
else:
d_cmd[cmd]()
There's far less room for copy and paste errors in this. But it's not supported. It's possible you could inspect the scope of process_user_input to find out if the function is available there. But that's a lot less pleasant than what I'm writing above. I frequently wonder why it is that the python team prefer to have programmers do either laborious 'if/else' clauses or else
duplicate strings as I've done above (think a copy / paste error in the first example where you were duplicating a function).
Perhaps an decorator mechanism could allow the functionality to be improved. But that would still be inferior to the 'fn' keyword I mention above. Adds an extra line and requires the annotation to be declared somewhere. Further, I for one find annotations much more complicated to understand than the idea of a function being directly inserted into a dictionary.
Ooh :) Decorators are definitely not bad. Thanks to #python and quotemstr in particular for this snippet:
def dict_add(d, key):
def _deco(func):
d[key] = func
return _deco
test_dict = {}
@dict_add(test_dict, 'a')
def _():
return 'sup'
print test_dict['a']()
2. Rebinding variables
While I was writing about a different scope problem I thought I'd write this.
It's not possible to rebind a variable that's held in an enclosing scope, with the exception of its treatment of the global scope. This is stupid, because it just acknowledges that what I'm trying to do is legitimate but provides a disgusting mechanism for achieving it.
def reformatter(debug=False):
x = 0
def inc():
if (debug):
print "x is being incremented"
x = x+1
def dec():
if (debug):
print "x is being decremented"
x = x+1
# ...
This would work:
def reformatter(debug=False):
x = [0]
def inc():
if (debug):
print "x is being incremented"
x[0] = x[0]+1
def dec():
if (debug):
print "x is being decremented"
x[0] = x[0]+1
# ...
So that's naturally what I end up doing when in this situation. Devteam are doing something about this in python 3k. But not in way that gets rid of global variables as I'd choose.
3. Classes - something python gets right
The annoyances I've listed also get to me in java. But python's handling of
classes pleases me.
I've found this very useful in writing ORM tools.
def entity_person():
class Cl(entity):
def __init__(self):
pass
return Cl()
Still, I think there's a lot to be said for the approach used by languages like io and javascript where there's no distinction between objects and classes, and where you can thus easily modify the functionality of a class at a later date. Io is particularly sexy in that it has methods to allow you to dynamically retrieve the syntax trees of its functions, and redesign them on the fly if you like.
0 comments:
Post a Comment