2011-08-25 8 views
6

Questa è una domanda abbastanza semplice, spero che tutti voi possa illuminarmi. Nell'esempio seguente come definisco __repr__ per essere impostato dinamicamente su self.name?Creazione dinamica di classi in python e __repr__

Grazie a tutti!

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 

Quello che sto cercando è questo

codice pseudo

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

risposta

3

Sto indovinando che si desidera

print results 

per tornare

["Sparcy", "Libs", "Darwin", "Aaple"] 
  1. Stampa di un elenco mostra il repr dei suoi elementi.
  2. repr(elt) è determinato da type(elt).__repr__.
  3. Poiché in questo caso gli elementi sono classi, è necessario impostare __repr__ per il tipo di classe.

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) 

cede

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

e

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

rendimenti

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

PS. Si noti che questa è una perversione di __repr__, poiché si suppone che l'repr di un oggetto sia una rappresentazione di stringa non ambigua dell'oggetto. Cioè, dovrebbe dare abbastanza informazioni per riprodurre l'oggetto. Probabilmente dovresti definire una diversa funzione print invece di scherzare con metaclassi.

+0

Sai come essere in grado di definire il tipo. Il modo in cui capisco questo funziona è se '__metaclass__' è definito che lo userà. Ne approfittate per il '__repr__'. Come faccio a non propagarlo per '__metaclass__'. Il __goal → type (Sparky) == Progetto__ – rh0dium

+0

@ rh0dium: Non sono sicuro di aver capito la domanda. Ho modificato il mio post in modo che print (type (klass)) 'stampasse' Project'. – unutbu

+0

Ma poi non è più dinamico. Cosa succede quando lo si getta su questo? 'Inputlist = 'Site =" Phoenix "Protocol =" Cheese "\ n' – rh0dium