Skip to content

Instantly share code, notes, and snippets.

@alvesjnr
Created June 1, 2012 13:22
Show Gist options
  • Save alvesjnr/2852116 to your computer and use it in GitHub Desktop.
Save alvesjnr/2852116 to your computer and use it in GitHub Desktop.
Por que usei __getattribute__

Seja o pequeno código, assim como listado no example.py do projeto tOSM:

from tosm.objects import *
from tosm.properties import *

class Address(Tobj):
    street = StringProperty()
    number = PositiveIntegerProperty()

class Person(Tobj):
    name = StringProperty()
    tel = PositiveIntegerProperty()
    address = ObjectProperty()

carlos = Person("Carlos", 99887766, Address(number=99, street="Koningstraat"))

dumped = carlos.dump()
recreated_carlos = Person.load(dumped)

Basicamente a parte que nos interessa são as duas últimas linhas: eu crio uma representação em estruturas Python dos meus objetos e, em seguida, recrio a classe (uma nova e inteiramente independente) a partir desta representação.

Para recriar o objeto do tipo Person, a classe Person provê um método da classe chamado load que consome esta estrutura python e devolve uma instância de si mesmo (esse método pertence na verdade à classe objects.Tobj, e é herdada pela classe Person).

Source do objects.Tobj

vamos dar uma olhada em como o método load recria uma instância de Tobj:

@classmethod
def load(cls, raw):
    """ 
        Recreate a tOSM object based on a structure
    """
    tobj = cls()

    for key,value in raw.items():
        if key in tobj._tosm_properties:

            meta_obj = cls.__getattribute__(cls,key)
            
            if isinstance(meta_obj, ObjectProperty):
                obj_class = meta_obj._object_definition
                obj = obj_class.load(value)
                setattr(tobj, key, obj)
            #MAIS COISAS QUE OMITI POR CONVENIÊNCIA!!!!
    return tobj

O método load recebe uma estrutura Python (dicionário) e itera sobre esta, procurando por properties da classe que casem com o nome da chave do dicionário recebido. Uma vez que se têm a tupla (key,value) da estrutura de entrada, para recriar eu preciso saber qual é a property da classe que têm o mesmo nome (nome contido em key). A princípio a maneira de se capturar o conteúdo (método, variável, etc.) de um objeto, tendo o nome do conteúdo é:

meta_obj = getattr(cls, key)

Porém o meu conteúdo é uma property, ela sobrescreveu o método get. Ou seja, quando eu fizer meta_obj = getattr(cls, key) invés de recuperar a property, eu estou invocando o método get da property.

A saída para isso é:

meta_obj = cls.__getattribute__(cls,key)

Com isso eu capturo a própria property e posso recriar uma instância dela com base no conteúdo passado dentro da estrutura para o método load.

obj_class = meta_obj._object_definition
obj = obj_class.load(value)
setattr(tobj, key, obj)

Se alguém achar um jeito mais simples, favor compartilhar a solução.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment