How to saw an instance of a class that is written inside a function?

Suppose I have this fragment inside a module

def func(params):
   class MyClass(object):
       pass

How can I select an instance of the MyClass class?

+5
source share
4 answers

You cannot, because the class definitions of the objects to be sorted must be in the scope of the imported module. Just put your class inside the module and you will go well.

However, in Python there is very little that cannot be achieved by hacking the internal elements of the machine (in this case sys.modules), but I would not recommend this.

+1
source

MyClass - func. , , , . :

def func(params):
    class MyClass(object):
        some_param = 100
        def __init__(self, *args):
            print "args:", args
        def blabla(self):
            self.x = 123
            print self.some_param
        def getme(self):
            print self.x

func.func_code - func, func.func_code.co_consts[2] - MyClass:

In : func.func_code.co_consts
Out: 
(None,
 'MyClass',
 <code object MyClass at 0x164dcb0, file "<ipython-input-35-f53bebe124be>", line 2>)

, - MyClass:

In : eval(func.func_code.co_consts[2])
Out: 
{'blabla': <function blabla at 0x24689b0>,
 '__module__': '__main__',
 'getme': <function getme at 0x2468938>,
 'some_param': 100,
 '__init__': <function __init__ at 0x219e398>}

, , , MyClass :

def map_functions(name, bases, dict):
    dict.update(eval(func.func_code.co_consts[2]))
    return type(name, bases, dict)

class NewMyClass(object):
    __metaclass__ = map_functions

n = NewMyClass(1, 2, 3, 4, 5)
>> args: (1, 2, 3, 4, 5)

n.blabla()
>> 100

n.getme()
>> 123
+1

, , , , exec(), __reduce__(), . , , :

from textwrap import dedent

# Scaffolding
definition = dedent('''
    class MyClass(object):
        def __init__(self, attribute):
            self.attribute = attribute
        def __repr__(self):
            return '{}({!r})'.format(self.__class__.__name__, self.attribute)
        def __reduce__(self):
            return instantiator, (definition, self.attribute)
''')

def instantiator(class_def, init_arg):
    """ Create class and return an instance of it. """
    exec(class_def)
    TheClass = locals()['MyClass']
    return TheClass(init_arg)

# Sample usage
import pickle
from io import BytesIO

stream = BytesIO()  # use a memory-backed file for testing

obj = instantiator(definition, 'Foo')  # create instance of class from definition
print('obj: {}'.format(obj))
pickle.dump(obj, stream)

stream.seek(0) # rewind

obj2 = pickle.load(stream)
print('obj2: {}'.format(obj2))

:

obj: MyClass('Foo')
obj2: MyClass('Foo')

, , , .

+1

, , Pickle , - object __class__.__name__ . , ( ) , .

, ( ), , .

The behavior for pickle and npickle can be set using methods __getstate__and __setstate__in the class - check docs, but even they, doing it right for a dynamic class, can be complicated, but I managed to create a working implementation of this for another SO question - mark my answer here: Dynamically salt parameterized subclass

+1
source

All Articles