What is and is not available to class methods in python?
My limited understanding is that the second argument types. FunctionTypes ( dict
) defines what is available to the function code. I am curious how this turns out when you create internal functions. To illustrate what I mean, if I try to copy a function dynamically:
a = 'test'
def foo():
print(a)
bar = types.FunctionType(
foo.__code__,
globals(),
'bar',
foo.__defaults__,
foo.__closure__
)
This seems to work with globals (), but I haven't missed anything? More confusing is the class method. If I do something like this:
a = 'test'
class Foo(object):
b = 'Foo prints this'
def myfunc():
print(a, self.b)
Bar = type('Bar', tuple(), dict())
Bar.b = 'Bar prints this'
ns = globals()
#should I do ns.update(something) here?
f = Foo.myfunc
Bar.myfunc = types.FunctionType(f.__code__, ns, 'myfunc', ...)
This example works, but not more complicated:
import imp
import builtins
class Foo(object):
def __init__(self):
super().__init__() # super(Foo, self) also fails
mod = imp.new_module('test')
mod.__builtins__ = builtins
mod.Foo = type('Foo', tuple(), dict())
f = Foo.__init__
ns = {}
ns.update(mod.__dict__) #missing something here
mod.Foo.__init__ = types.FunctionTypes(f.__code__, ns, '__init__', ...)
Can anyone please highlight what should be in ns
? What is available for a class method and what is not?
I'm not trying to get this code to work, I'm looking more for an explanation of why it doesn't.
source to share
The problem is that "copying" an attribute __closure__
does not create a copy; that the execution context itself, in which the function object itself ( def __init__
) was executed; in support of lexical rules in python. Taking a look:
>>> [cell.cell_contents for cell in f.__closure__]
[<class '__main__.Foo'>]
Unsurprisingly, this is the class in which it was defined. I'm not sure about an easy way to create a new object cell
other than using exec
it to create a new class and method; You could probably copy the new cell to additional methods to be added to the new class, but both the core and the class will be completely new.
source to share