Envolvendo um objeto Python

votos
1

Eu gostaria de serializar objetos Python de e para o formato plist (isto pode ser feito com plistlib). Minha idéia era escrever um PlistObject classe que envolve outros objetos:

def __init__(self, anObject):
     self.theObject = anObject

e fornece um método write:

def write(self, pathOrFile):
    plistlib.writeToPlist(self.theObject.__dict__, pathOrFile)

Agora, seria bom se o PlistObject se comportou exatamente como próprio objeto embrulhado, o que significa que todos os atributos e métodos são de alguma forma encaminhado para o objeto embrulhado. Eu percebo que os métodos __getattr__e __setattr__pode ser usado para operações de atributos complexos:

    def __getattr__(self, name):
         return self.theObject.__getattr__(name)

Mas então é claro que eu correr para o problema que o construtor agora produz uma recursão infinita, uma vez que também self.theObject = anObjecttenta acessar o objeto embrulhado.

Como posso evitar isso? Se a idéia parece ser uma má um, diga-me também.

Publicado 19/05/2009 em 20:27
fonte usuário
Em outras línguas...                            


3 respostas

votos
3

A menos que eu estou faltando alguma coisa, isso vai funcionar muito bem:

def __getattr__(self, name):
    return getattr(self.theObject, name)

Edit: para aqueles que pensam que a pesquisa de self.theObjectresultará em uma chamada recursiva infinita __getattr__, deixe-me mostrar-lhe:

>>> class Test:
...     a = "a"
...     def __init__(self):
...         self.b = "b"
...     def __getattr__(self, name):
...         return 'Custom: %s' % name
... 
>>> Test.a
'a'
>>> Test().a
'a'
>>> Test().b
'b'
>>> Test().c
'Custom: c'

__getattr__só é chamado como um último recurso . Desde theObjectpode ser encontrada em __dict__, sem problemas surgem.

Respondeu 19/05/2009 em 20:41
fonte usuário

votos
2

Mas então é claro que eu correr para o problema que o construtor agora produz uma recursão infinita, uma vez que também self.theObject = anObject tenta acessar o objeto embrulhado.

É por isso que o manual sugere que você faça isso para todos atributo "real" acessos.

theobj = object.__getattribute__(self, "theObject")
Respondeu 19/05/2009 em 20:36
fonte usuário

votos
1

Fico feliz em ver os outros têm sido capazes de ajudá-lo com a chamada recursiva para __getattr__. Desde que você pediu para comentários sobre a abordagem geral de serialização para Plist, eu só queria dialogar com alguns pensamentos.

Implementação plist do Python lida com tipos básicos apenas, e não prevê qualquer mecanismo de extensão para que você possa instruí-lo sobre a serialização / desserialização de tipos complexos. Se você definir uma classe personalizada, por exemplo, writePlist não será capaz de ajudar, como você descobriu desde que você está passando a instância é __dict__para serialização.

Isto tem algumas implicações:

  1. Você não será capaz de usar isso para seriar quaisquer objetos que contêm outros objetos do tipo não-básicos sem convertê-los a um __dict__, e assim-on de forma recursiva para toda a rede gráfico.

  2. Se você rolar o seu próprio gráfico de rede walker para serializar todos os objetos não-básicos que podem ser alcançados, você vai ter que se preocupar com círculos no gráfico onde um objeto tem um outro em uma propriedade, que por sua vez detém uma referência de volta para o primeiro , etc etc.

Dado então, você pode querer olhar para pickle em vez como ele pode lidar com tudo isso e muito mais. Se você precisar o formato plist por outras razões, e você está certo você pode furar a "simples" dicts objeto, então você pode querer usar apenas uma função simples ... tentar ter o PlistObject simulada cada função possível no contido objeto é uma cebola com potencialmente muitas camadas como você precisa lidar com todas as possibilidades da instância embrulhado.

Algo tão simples como isso pode ser mais Python, e manter a usabilidade do objeto embrulhado mais simples por não envolvê-lo em primeiro lugar:

def to_plist(obj, f_handle):
    writePlist(obj.__dict__, f_handle)

Eu sei que não parece muito sexy, mas é muito mais sustentável na minha opinião do que um invólucro dadas as graves limitações do formato plist, e certamente melhor do que forçar artificialmente todos os objetos em seu aplicativo para herdar de uma classe base comum quando não há nada em seu domínio de negócio que realmente indica os objetos díspares estão relacionados.

Respondeu 19/05/2009 em 23:30
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more