Defining constants in python class, is self really needed? Defining constants in python class, is self really needed? python python

Defining constants in python class, is self really needed?


When you assign to names in the class body, you're creating attributes of the class. You can't refer to them without referring to the class either directly or indirectly. You can use Foo.VAGUE as the other answers say, or you can use self.VAGUE. You do not have to assign to attributes of self.

Usually, using self.VAGUE is what you want because it allows subclasses to redefine the attribute without having to reimplement all the methods that use them -- not that that seems like a sensible thing to do in this particular example, but who knows.


try instead of:

self.status = VAGUE

this one:

self.status = Foo.VAGUE

you MUST specify the class


This one is NOT RECOMMENDED FOR ANY CODE by any means, but an ugly hack like below can be done.I did this just to have better understanding of Python AST API, so anyone who uses this in real-world code should be shot before it does any harm :-)

#!/usr/bin/python# -*- coding: utf-8-unix -*-## AST hack to replace symbol reference in instance methods,# so it will be resolved as a reference to class variables.#import inspect, types, astdef trim(src):    lines = src.split("\n")    start = lines[0].lstrip()    n = lines[0].index(start)    src = "\n".join([line[n:] for line in lines])    return src## Method decorator that replaces symbol reference in a method# so it will use symbols in belonging class instead of the one# in global namespace.#def nsinclude(*args):    # usecase: @nsinclude()    # use classname in calling frame as a fallback    stack = inspect.stack()    opts  = [stack[1][3]]    def wrap(func):        if func.func_name == "tempfunc":            return func        def invoke(*args, **kw):            base = eval(opts[0])            src = trim(inspect.getsource(func))            basenode = ast.parse(src)            class hackfunc(ast.NodeTransformer):                def visit_Name(self, node):                    try:                        # if base class (set in @nsinclude) can resolve                        # given name, modify AST node to use that instead                        val = getattr(base, node.id)                        newnode = ast.parse("%s.%s" % (opts[0], node.id))                        newnode = next(ast.iter_child_nodes(newnode))                        newnode = next(ast.iter_child_nodes(newnode))                        ast.copy_location(newnode, node)                        return ast.fix_missing_locations(newnode)                    except:                        return node            class hackcode(ast.NodeVisitor):                def visit_FunctionDef(self, node):                    if func.func_name != "tempfunc":                        node.name = "tempfunc"                        hackfunc().visit(node)            hackcode().visit(basenode)            newmod = compile(basenode, '<ast>', 'exec')            eval(newmod)            newfunc = eval("tempfunc")            newfunc(*args, **kw)        return invoke    # usecase: @nsinclude    if args and isinstance(args[0], types.FunctionType):        return wrap(args[0])    # usecase: @nsinclude("someclass")    if args and args[0]:        opts[0] = args[0]    return wrapclass Bar:    FOO = 987    BAR = 876class Foo:    FOO = 123    BAR = 234    # import from belonging class    @nsinclude    def dump1(self, *args):        print("dump1: FOO = " + str(FOO))    # import from specified class (Bar)    @nsinclude("Bar")    def dump2(self, *args):        print("dump2: BAR = " + str(BAR))Foo().dump1()Foo().dump2()