Is it possible for me to create a runtime class in Python?

Asked

Viewed 876 times

3

I wanted to create a runtime class to do some database updates, for example, but without being dependent on DBMS but using python and I wanted to know if it is possible to create these classes at runtime.

  • It has some techniques, but creating the class is the least of the problems, to do this you need to architect the application very well. It’s hard, but it’s possible, if you just use it to make the software flexible. I know a big company that did wrong and it costs him and his clients millions. I like the idea, but except in very general situations it takes a lot of work to do well and need to have reason to compensate.

  • Can you explain better what you want to do? Are you sure that what you need is to create a class and not just an instance?

  • For access to DBMS I would opt for the Sqlalchemy. But somehow I put my answer.

2 answers

5

In Python, it is trivial to create runtime classes - and with some work and care, you can even create instrumented classes with ORM (Relational Object Mapping) functionalities that work well.

Your system makes good use of them, of course, will depend on other components - not just the part that "talks" to the database has how to use data from these dynamically constructed classes to do something useful. (Which fields will be displayed in the UI? In what order? Which users can modify which fields?? )

It is possible to build an example that introspectes the database and from there is completely dynamic. (And it will actually make little difference whether the elements of a given table are represented by a Python class internally, or in a "dumb" dictionary structure) - but as a rule is to melor you define well some models for your system and have these models - at least some fields - placed as code in your system.

All this said, to create a new class in Python, just call the constructor type, passing the parameters "name", "bases" and "namespace" - the latter is a dictionary with the equivalent statements that we put in the body of a class written with the keyword class:

def init(self):
   print("Inicializando ", self)

MinhaClasse = type("MinhaClasse", (object,), {"__init__": init})

MinhaClasse()

Pronto - Minhaclase was created at runtime with values that could be in vaiables. Now, making some use of it is another story. (For example, you can set a "attributes" parameter in the namespace - and make the __init__ can receive these attributes as named Parameters and automatically assign them to the instance:

class Base:
    atributos = ""
    def __init__(self, **kwargs):
         for atributo in atributos.split():
             setattr(self, atributo, kwargs.pop(atributo, None))

ClassePessoa = type("ClassePessoa", (Base,), {'atributos': 'nome idade'})

p1 = ClassePessoa(nome='Lucas', idade=23)
print(p1.nome) 

5

(TL;DR)

It is possible and indeed relatively easy, although laborious. I will reproduce an explanation/example well spread on the Internet:

First of all, let’s focus on the relationship between type and class. When we define classes we can ask ourselves "what happens behind the scenes". We can see that if we apply type to an object, the return is the class from which that object was instantiated.

a = [1, 2, 3]
b = "Hello"
print(type(a), type(b))
<class 'list'> <class 'str'>

If we apply type in the class name, we get the "type" class:

print(type(list), type(str))
<class 'type'> <class 'type'>

This is similar to applying type in type(a) and type(b)

a = [4, 5, 9]
b = "Hello"
print(type(a), type(b))
print(type(type(a)), type(type(b)))
<class 'list'> <class 'str'>
<class 'type'> <class 'type'> 

A user-defined class (or class object) is an instance of the "type" class. As you can see, classes are created from type. In python3 there is no difference between "classes" and "types". These terms can in many cases be used as sinomimos.

The fact that classes are instances of a "type" class allows or supports the use of metaclasses. We can create classes, which inherit directly from the "type" class, so a metaclass is a subclass of the "type" class".

Type can be called with three arguments

type(classname, superclasses, attributes_dict)

When type is called with 3 arguments, it returns a new object type. This provides a way to dynamically delve a class.

  • "classname" is the string that defines the class name and will become the attribute name;
  • "superclass" is a list or tuple with the superclasses of our class. This parameter will become the attribute groundwork
  • The attributes_dict parameter is a dictionary that will function as the namespace of our class. Contains the definitions of the class body and will become the attribute Dict

Let’s look at a simple definition

class A:
    pass
x = A()
print(type(x))
<class '__main__.A'>

We can use "type" to define the class A:

A = type("A", (), {})
x = A()
print(type(x))
<class '__main__.A'>

When we call "type", the method call type is called. The method call executes two other methods: new and init:

type.__new__(typeclass, classname, superclasses, attributedict)
type.__init__(cls, classname, superclasses, attributedict)

The method new creates and returns the new object of type class and then the method init initializes the new created class.

See two identical classes (Robot), defined in two completely different ways in syntactic terms:

class Robot1:
    counter = 0
    def __init__(self, name):
        self.name = name
    def sayHello(self):
        return "Hi, I am " + self.name


def Rob_init(self, name):
    self.name = name

Robot2 = type("Robot2", 
              (), 
              {"counter":0, 
               "__init__": Rob_init,
               "sayHello": lambda self: "Hi, I am " + self.name})

Now let’s instantiate the two classes and present their attributes:

r1 = Robot('Robocop')
print(r1.name)
print(r1.sayHello())
print(r1.__dict__)
print(r1.__dict__)  
Robocop
Hi, I am Robocop
{'name': 'Robocop'}
{'name': 'Robocop'}

r2 = Robot2('Robocop')
print(r2.name)
print(r2.sayHello())
print(r2.__dict__)
print(r2.__dict__) 
Robocop
Hi, I am Robocop
{'name': 'Robocop'}
{'name': 'Robocop'}

With this explanation it is possible to notice that, in python, it is relatively easy (compared to other languages/platforms) to define classes dynamically.

See this explanation and code running on a notebook jupyter.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.