style query: function attributes for return codes?
Steven Bethard
steven.bethard at gmail.com
Fri Dec 10 11:40:25 EST 2004
george young wrote:
> This is obviously just evil, since a misspelling in the string
> return is treacherous. I'm considering function attributes:
>
> def get_connection():
> if tcp_conn():
> if server_allows_conn():
> return get_connection.GOOD
> else:
> return get_connection.BAD_AUTH
> else:
> return get_connection.NO_SERVER
> get_connection.GOOD = 1
> get_connection.BAD_AUTH = 2
> get_connection.NO_SERVER = 3
Although in most cases this is probably okay, you're not guaranteed that
the name of your function will stay the same, so there are some hazards
in this style:
>>> def f(x):
... return f.y * x
...
>>> f.y = 100
>>> f(2)
200
>>> g, f = f, None
>>> g(2)
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 2, in f
AttributeError: 'NoneType' object has no attribute 'y'
One option is to turn your function into a class:
class get_connection(object):
GOOD = 1
BAD_AUTH = 2
NO_SERVER = 3
def __new__(cls):
if tcp_conn():
if server_allows_conn():
return cls.GOOD
else:
return cls.BAD_AUTH
else:
return cls.NO_SERVER
This is a little sneaky here -- because you only need shared state
between all instances of get_connection, you don't actually ever need to
create an instance. So I've overridden __new__ to return the result of
the function instead. This allows you to call the function just like
you would have before. I haven't tested the code above, but here's a
simpler example that works:
>>> class look_ma_no_function(object):
... X = 42
... def __new__(cls):
... return cls.X
...
>>> look_ma_no_function()
42
If you need to do this with a function that takes more parameters, you
can just add them to the __new__ declaration:
>>> class look_ma_no_function(object):
... X = 42
... def __new__(cls, s):
... return cls.X / float(len(s))
...
>>> look_ma_no_function('answer to life the universe and everything')
1.0
Despite the fact that this particular use seems a little sneaky to me, I
do usually end up turning most functions that seem to need attributes
into classes (usually with a __call__ method defined).
Steve
More information about the Python-list
mailing list