There is Binding of data in Python

Asked

Viewed 45 times

1

Hey there, you guys. You know some kind of Python data that you commonly have in Java frameworks, such as JSF, Spring and so on. Because I’ve used Flask and Django and I haven’t seen a similar feature in both, so I have to set the attribute in my classes. I don’t know if this is really common in the Python world, because if it isn’t, then I’ve been very ill-used in Java rsrs... Thanks in advance.

It would be an automatic way to set attributes in a class, for example:

class Endereco(object):
  logradouro = None
  numero = None
class Pessoa(object):
  nome = None
  idade = None
  endereco = Endereco

params = { "nome": "Lol", "idade": 30, "endereco": { "logradouro": "rua longe pra cacete", "numero": "300" } }

p = binding(params, Pessoa) // método mágico que cria um o objeto do tipo Pessoa a partir do mapa
  • There’s a better way to detail what that would be Binding desiring?

  • ready! partner updated the post to better explain my question

  • I believe that there is nothing of this kind, not least because Python is not strongly typed, like Java. There is a function that can do this, but I believe that manually is more appropriate. Here There is a code that I made very shallow that does what it wants, but I reaffirm, I did it superficially only for testing. Maybe you can build on it and do something interesting.

  • @Andersoncarloswoss thank you so much for your kindness to write an example, it will already be of great help to me

1 answer

0

It doesn’t exist in the standard library - but it’s something relatively easy to do by placing the code for it in your base class - and calling the constructor of that class.

Unfortunately this leaves many ways to do this - right now, on the E-more list python-ideas is debating a possible inclusion of a standardized way of doing this (after accessing the link, click on thread at the bottom of the page to see all E-Oover) - in this discussion, u am in favor of a developer - and in no way a new syntax, as the original thread author suggests.

But a base class is even simpler than a developer - so - Python allows a function to receive any number of named parameters, without knowing their names beforehand - just prefix a parameter with ** in the asymmetry of the function the various parameters are paired as a dictionary. Similarly, in calling a function, prefix an object of the type mapping (as a dictionary) with ** unpack all dictionary items as parameters for a function.

This allows us to have in the method __init__ of the base class a code that receives all parameters, check if the attribute exists in the class, and, if it exists, make the Binding of it. As a gift, you can even implement type-checking by checking whether a parameter is a sub-class of the parameter declared in the class:

class Base:
    def __init__(self, **kwargs):
        cls = self.__class__
        # itera em uma cópia dos items do dicionário, 
        # permitindo que ele seja alterado durante o "for":
        for name, value in list(kwargs.items()):
            # Verifica se o parâmetro existe na própria classe,
            # caso contrário, mantem o mesmo no dicionário.
            if not hasattr(cls, name):
                continue
            if not isinstance(value, getattr(cls, name)):
                raise TypeError("Incorrect parameter type passed for {}. An '{}' was expected.".format(
                    cls.__name__, getattr(cls, name).__name__))
            setattr(self, name, value)
            del kwargs[name]


class Pessoa(Base):
    nome = str
    idade = int
    endereco = dict

And in interactive mode:

In [104]: params = { "nome": "Lol", "idade": 30, "endereco": { "logradouro": "rua longe pra cacete", "numero": "300" } }
     ...: 

In [105]: p  = Pessoa(**params)

In [106]: p.nome, p.idade, p.endereco
Out[106]: ('Lol', 30, {'logradouro': 'rua longe pra cacete', 'numero': '300'})

In [107]: params["idade"] = "muito velho"

In [108]: p2 = Pessoa(**params)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
(...)
TypeError: Incorrect parameter type passed for Pessoa. An 'int' was expected.
  • In this case, the defined attributes would be class attributes. To keep them as instance attributes it would be necessary to define them within the initializer and call the class initializer Base manually (type that)?

  • Yes - c The Base class initializer uses class attributes as guides to know which instance attributes to create and which types to create. But note that if you do not need a specific initializer in derived classes, you do not need to call the Base initializer - it will be called automatically.

Browser other questions tagged

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