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()