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
= chooseclass("asd")
theclass = theclass() theobj
Frame Objects
Global Frame
chooseclass -----> function chooseclass(name)
theclass -----> Foo class
theobj -----> Foo instance
2 List and Ref
= 1 # create int(1) literal, bind it to a in Global Frame
a = a # bind b to the same literal that a binds to
b = 2 # create int(2) literal, bind it to a in Global Frame a
Frame Objects
Global Frame
a 2 b 1
The 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.
= 5 # name `i` refers to object `5`
i = i # ???
j = 3 # name `j` refers to object `3` j
int three=3, five=5; // objects
int *i, *j; // names
= &five; // name `i` refers to position of object `5`
i = i; // name `j` refers to referent of `i`
j = &three; // name `j` refers to position of object `3` j
= [1,2,3] # name `i` refers to object `[1, 2, 3]`
i = i # name `j` refers to referent of `i`
j 0] = 5 # ??? i[
typedef struct{
int *elements[3];
} list; // length 3 `list` type
int one = 1, two = 2, three = 3, five = 5;
= {&one, &two, &three}; // objects
list values *i, *j; // names
list = &values; // name `i` refers to object `[1, 2, 3]`
i = i; // name `j` refers to referent of `i`
j ->elements[0] = &five; // leading element of `i` refers to object `5` i
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):
= 0
cnt def wrapper(*argv):
nonlocal cnt
= cnt + 1
cnt print(argv,cnt*"-", 'Decorated!')
= g(*argv)
ans = cnt - 1
cnt print(cnt*"-",'rev')
return(ans)
return(wrapper)
def cov(f):
= copy.deepcopy(f)
e = dec(e)
e return e
= cov(fib) really means
fib = cov(fib)
g = g
fib
4) t(
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):
= 0
cnt def wrapper(*argv):
nonlocal cnt
= cnt + 1
cnt print(argv,cnt*"-", 'Decorated!')
= g(*argv)
ans = cnt - 1
cnt print(cnt*"-",'rev')
return(ans)
return(wrapper)
globals()[f.__name__]=dec(globals()[f.__name__])
return 0
big(fib)5) fib(