2011-08-25 11 views
6

Esta es una pregunta bastante sencilla con la esperanza de que todos ustedes puedan aclararme. En el siguiente ejemplo, ¿cómo defino __repr__ para establecerlo dinámicamente en self.name?Creando dinámicamente las clases en python y __repr__

¡Gracias a todos!

import re 

inputlist = 'Project="Sparcy" Desc=""\nProject="Libs" Desc=""\nProject="Darwin" Desc=""\nProject="Aaple" Desc="The big project"' 

regex = re.compile('([^ =]+) *= *("[^"]*"|[^ ]*)') 

results = [] 
for project in inputlist.split("\n"): 
    items = [ (k.strip(), v.strip()) for k, v in regex.findall(project)] 
    if len(items) < 2: 
     print("Houston we have a problem - Only %s k/v pair found for %s" % (len(items), project)) 
     continue 
    item_dict = dict(items[1:]) 
    item_dict['name'] = items[0][1] 
    klass = type(items[0][0], (object,), item_dict) 
    results.append(klass) 

print results 

Lo que estoy buscando es el código pseudo

for result in results 
type(result) → Project 
print result → Sparky 

Respuesta

3

que supongo que desea

print results 

para volver

["Sparcy", "Libs", "Darwin", "Aaple"] 
  1. La impresión de una lista muestra la representación de sus elementos.
  2. repr(elt) está determinado por type(elt).__repr__.
  3. Dado que en este caso los elementos son clases, debe establecer __repr__ para el tipo de la clase.

import re 

inputlist = '''\ 
Project="Sparcy" Desc="" 
Project="Libs" Desc="" 
Project="Darwin" Desc="" 
Project="Aaple" Desc="The big project" 
Site="Phoenix" Protocol="Cheese"''' 

regex = re.compile('([^ =]+) *= *("[^"]*"|[^ ]*)') 

results = [] 
for project in inputlist.split("\n"): 
    items = [ (k.strip(), v.strip()) for k, v in regex.findall(project)] 
    if len(items) < 2: 
     print("Houston we have a problem - Only %s k/v pair found for %s" % (len(items), project)) 
     continue 
    item_dict = dict(items[1:]) 
    item_dict['name'] = items[0][1] 
    projectname=items[0][0] 
    metametaklass=type('meta_'+projectname,(type,),{'__repr__':lambda cls: cls.__name__}) 
    metaklass=metametaklass(projectname,(type,),{'__repr__':lambda cls: cls.name}) 
    klass=metaklass(projectname+'_class', (object,), item_dict) 
    results.append(klass) 

print(results) 

produce

["Sparcy", "Libs", "Darwin", "Aaple", "Phoenix"] 

y

for result in results: 
    print(type(result)) 
    print(result)  
    print('-'*80) 

rendimientos

Project 
"Sparcy" 
-------------------------------------------------------------------------------- 
Project 
"Libs" 
-------------------------------------------------------------------------------- 
Project 
"Darwin" 
-------------------------------------------------------------------------------- 
Project 
"Aaple" 
-------------------------------------------------------------------------------- 
Site 
"Phoenix" 
-------------------------------------------------------------------------------- 

PD. Tenga en cuenta que esta es una perversión de __repr__, ya que se supone que el repr de un objeto es una representación de cadena inequívoca del objeto. Es decir, se supone que debe dar suficiente información para reproducir el objeto. Probablemente debería definir una función print diferente en lugar de jugar con metaclases.

+0

¿Sabes cómo poder definir el tipo. La forma en que entiendo esto funciona es que si '__metaclass__' está definido, usará eso. Estás aprovechando eso para el '__repr__'. ¿Cómo no propagar eso para '__metaclass__'. The __goal → type (Sparky) == Project__ – rh0dium

+0

@ rh0dium: No estoy seguro de entender la pregunta. Edité mi publicación para que 'print (type (klass))' imprimiera 'Project'. – unutbu

+0

Pero luego ya no es dinámico. ¿Qué sucede cuando lo haces esto? 'Inputlist = 'Sitio =" Phoenix "Protocolo =" Queso "\ n' – rh0dium

Cuestiones relacionadas