Frames Scope and Python
Posted on September 2, 2022
Tags: codeetc
1 Meta-Classes
- Even Class declarations are objects which are instantiated by Meta-classes
- Meta-classes construct Classes
- Classes construct Objects
def chooseclass(name):
class Foo(object):
pass
return Foo
theclass = chooseclass("asd")
theobj = theclass() Frame Objects
Global Frame
chooseclass -----> function chooseclass(name)
theclass -----> Foo class
theobj -----> Foo instance
2 List and Ref
a = 1 # create int(1) literal, bind it to a in Global Frame
b = a # bind b to the same literal that a binds to
a = 2 # create int(2) literal, bind it to a in Global Frame Frame Objects
Global Frame
a 2
b 1The above code does not create any reference to any objects.
Python names work like pointers with automatic de/referencing but do not allow explicit pointer operations. Other targets represent indirections, which behave similar to pointers.
i = 5 # name `i` refers to object `5`
j = i # ???
j = 3 # name `j` refers to object `3`int three=3, five=5; // objects
int *i, *j; // names
i = &five; // name `i` refers to position of object `5`
j = i; // name `j` refers to referent of `i`
j = &three; // name `j` refers to position of object `3`i = [1,2,3] # name `i` refers to object `[1, 2, 3]`
j = i # name `j` refers to referent of `i`
i[0] = 5 # ???typedef struct{
int *elements[3];
} list; // length 3 `list` type
int one = 1, two = 2, three = 3, five = 5;
list values = {&one, &two, &three}; // objects
list *i, *j; // names
i = &values; // name `i` refers to object `[1, 2, 3]`
j = i; // name `j` refers to referent of `i`
i->elements[0] = &five; // leading element of `i` refers to object `5`import copy
def fib(n):
if n == 0:
return 1
if n == 1:
return 1
else:
return fib(n-2)+fib(n-1)
def dec(g):
cnt = 0
def wrapper(*argv):
nonlocal cnt
cnt = cnt + 1
print(argv,cnt*"-", 'Decorated!')
ans = g(*argv)
cnt = cnt - 1
print(cnt*"-",'rev')
return(ans)
return(wrapper)
def cov(f):
e = copy.deepcopy(f)
e = dec(e)
return e
fib = cov(fib) really means
g = cov(fib)
fib = g
t(4)Scoping + pyObject pointerlike behavior means we can post modify global scoped functions after wrapping them.
It is possible to design a hacking solution for a wrapper. Why must we do assignment in the global scope f=dec(f)? Because the globalscope is the scope that allows us full access to all the variable names aka pointers to our target function which is what we need access to, to redirect them to our wrapped function.
def fib(n):
if n == 0:
return 1
if n == 1:
return 1
else:
return fib(n-2)+fib(n-1)
def big(f):
print(f.__name__)
def dec(g):
cnt = 0
def wrapper(*argv):
nonlocal cnt
cnt = cnt + 1
print(argv,cnt*"-", 'Decorated!')
ans = g(*argv)
cnt = cnt - 1
print(cnt*"-",'rev')
return(ans)
return(wrapper)
globals()[f.__name__]=dec(globals()[f.__name__])
return 0
big(fib)
fib(5)