This toy module shows a way to define symbols inside functions, using a decorator. Idea derived from recipe 303057 by Shai Berger.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | """
symbols.py -- by bearophile, V.1.0 Jan 23 2007
This module is probably an useless toy to manage symbols with CPython.
The symbol 'car' can be defined with as Symbol('s_car') or they are
automatically instantiated inside functions/methods with the help
of the @withsymbols decorator.
Some ideas come from Pythologic.py by Shai Berger, Cookbook recipe n.303057
"""
class Symbol:
"""Symbol class. A symbol 'car' has to be defined as:
Symbol('inprefixcar')
Where inprefix is a class attribute that's usually s_
Or you can use the @withsymbols decorator."""
inprefix = "s_"
outprefix = "$"
def __init__(self, inname):
inname = str(inname)
if not inname or not inname.startswith(Symbol.inprefix):
raise TypeError("Symbol names must be defined with a starting "
+ Symbol.inprefix)
self.__name = Symbol.outprefix + inname[len(Symbol.inprefix):]
self.__hash = hash(self.__name)
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return self.__name == other.__name
def __ne__(self, other):
if not isinstance(other, self.__class__):
raise True
return self.__name != other.__name
def __cmp__(self, other):
if not isinstance(other, self.__class__):
raise TypeError("Symbols can be compared only with other Symbols")
return cmp(self.__name, other.__name)
def __hash__(self):
return self.__hash
def __nonzero__(self):
return True
def __repr__(self): # this may become __str__
return self.__name
def getrepr(self): # this may become __repr__
return "%s('%s%s')" % (self.__class__.__name__, Symbol.inprefix,
self.__name[len(Symbol.outprefix):])
repr = property(getrepr)
def withsymbols(func):
"""decorator, if applied to a function, allows it to use Symbols,
creating them when needed when the function is defined. A symbol
name must start with inprefix (usually s_)."""
# Ideas derived from Pythologic.py by Shai Berger
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303057
try:
code = func.func_code
except:
raise TypeError, "function or method argument expected"
names = code.co_names
locally_defined = code.co_varnames
globally_defined = func.func_globals
defined = set(locally_defined).union(globally_defined)
undefined = set(names) - defined
# Update the global scope of the function func, add definitions
# for all undefined names starting with inprefix
for name in undefined:
if name.startswith(Symbol.inprefix):
func.func_globals[name] = Symbol(name)
return func
if __name__ == '__main__':
@withsymbols
def symbols_demo():
print "Symbols demo:"
print " {s_a:5, s_b:6, s_c:s_a}:", {s_a:5, s_b:6, s_c:s_a}
print " Symbol('s_bar'):", Symbol('s_bar')
some_symbols = set([(s_a, s_b), s_c, s_d])
print " some_symbols:", some_symbols
print " s_car == s_car:", s_car == s_car
print " s_car is s_car:", s_car is s_car
print " s_car, repr(s_car), s_car.repr:", s_car, repr(s_car), s_car.repr
print " s_b > s_a, s_b >= s_c:", s_b > s_a, s_b >= s_c
print ' "|" + str(s_car) + "|":', "|" + str(s_car) + "|"
print " sorted([s_d, s_a, s_c, s_f, s_e]):", sorted([s_d, s_a, s_c, s_f, s_e])
s_hello = 5 # s_name names can be defined anyway in the normal way
print " s_hello:", s_hello
symbols_demo()
|
I have no idea if such symbols may become useful for something in Python, they may be just a toy.
Tags: shortcuts