1

I´m currently creating a program which will be able to create classes at runtime. What I want is to load a json file into the script and from there create classes and inherited classes. In this file the class names will come as strings, this is why I need a solution that takes a string "A" and converts it into class A(metaclass=Metaclass) .I have learned a bit of metaclasses and understand some of it, however, I failed to create classes due to the fact that I´m not able to declare the name of the class. I came to a clumsy solution by using globals(). However, I was wondering if there is a more pythonic solution.

class MetaFoo(type):

    def __new__(cls,name,bases,attr):
        print(f"{name} is invoking {cls.__name__}")
        return super().__new__(cls,name,bases,attr)

    def creator(name,bases,attr):
        globals()[name] = type(name,bases,attr)

class Foo(metaclass=MetaFoo):
    pass

class SubFoo1(Foo):
    pass

class SubFoo2(Foo):
    pass

class InheritFoo(SubFoo1,SubFoo2):
    pass

print("-"*30)
MetaFoo.creator("Z",(Foo,),{})

The output would be:

Foo is invoking MetaFoo
SubFoo1 is invoking MetaFoo
SubFoo2 is invoking MetaFoo
InheritFoo is invoking MetaFoo
------------------------------
Z is invoking MetaFoo

Now I can create subclasses of Foo with creator(), however, I understand I'm having the wrong approach and my code is not able to produce directly subclasses of MetaFoo. So here are my three questions.

  1. How can I create classes from Metaclass using a string loaded externally? Not using metaclass type() like I did because if I were to use type() to create classes there would be no point to create a custom metaclass. I need to use metaclass not only because it lets you create new classes dinamically, but becuase it offers many functionalities like that I need in my program.

  2. I´m going to be dealing with big data, probably some millions of SQLite3 lines. Each line corresponds to a purchase and each class to a category, subcategory, etc. Performance wise, ¿Is having million of active objects, in this case, instances of the classes created by Metaclass, going to slow down the program or not being able to compute at all?

  3. I know how to keep track of new classes being created via metaclass, but ¿How do I keep track of instances of the classes, which magic method and how should I modify it?

Thank you for your time.

Jose J
  • 13
  • 2
  • I don't have time right now to write out a full answer however you could just assign the class object to a different name like so: `Z = Foo` and then instances could be created using `z = Z()`. – mattjegan Mar 05 '18 at 00:59
  • [How to keep track of class instances](https://stackoverflow.com/questions/12101958/how-to-keep-track-of-class-instances) – Patrick Haugh Mar 05 '18 at 01:01

1 Answers1

1

Instead of using type, call MetaFoo directly.

globals()[name] = MetaFoo(name, (), {})

Jeff Knupp mentions doing something similar with metaclasses and databases for his sandman library in a post here. You might want to look at his code and see if he's written anything more on that subject.

Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • I didn´t realize the answer was so simple, thank you. ¿What do you think about the second question I made? Would having millions of instances have performance issues? – Jose J Mar 05 '18 at 12:38
  • Millions of instances is a lot. Make a single instance and use [`sys.getsizeof`](https://docs.python.org/3/library/sys.html#sys.getsizeof) to see how big it is. (Also use `getsizeof` to determine the size of any container objects that object references). Then multiply that by the number of objects you expect to have. I would do everything in my power not to have millions of instances to manage. – Patrick Haugh Mar 05 '18 at 13:20