style query: function attributes for return codes?
george young
gry at ll.mit.edu
Fri Dec 10 14:35:23 EST 2004
On Fri, 10 Dec 2004 16:40:25 GMT
Steven Bethard <steven.bethard at gmail.com> threw this fish to the penguins:
> 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'
Yes, I was worried about this.
> 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
Hmm, this is quite clever, and indeed does what I want.
I hesitate to adopt it, though, because it *looks* sneaky.
For readable and maintainable code, I think it may be a bit
too hackish... The original impetus for my post was to find
a clear, maintainable form.
I wonder about returning an object that tests True if all is
ok, and has boolean attributes to query if not True...:
def get_connection():
class Ret:
def __init__(self, badauth=False, noserver=False):
self.badauth = badauth
self.noserver = noserver
def __nonzero__(self):
return not(self.badauth and self.noserver)
if tcp_conn():
if server_allows_conn():
return Ret()
else:
return Ret(badauth=True)
else:
return Ret(noserver=True)
ret = get_connection()
if not ret:
if ret.badauth:
...
still seems a bit cumbersome in definition,
though the use is not bad...
-- George
--
"Are the gods not just?" "Oh no, child.
What would become of us if they were?" (CSL)
More information about the Python-list
mailing list