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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to