2015-10-15 7 views
7

Esempio eccellente per python2 here. La mia traduzione in python3 (mostrata sotto) funziona in tutti i miei test.Il modo più veloce per convertire chiavi e valori di dict da `bytes` a` str` in python3

def convert(data): 
    if isinstance(data, bytes): 
     return data.decode('ascii') 
    elif isinstance(data, dict): 
     return dict(map(convert, data.items())) 
    elif isinstance(data, tuple): 
     return map(convert, data) 
    else: 
     return data 

Sembra che sto usando questo molto per le librerie che sono state trasferite da py2 a py3.

Qualcuno ha un design migliore per lo stesso compito? Questo potrebbe essere ottimizzato?

+1

Cosa c'è di sbagliato con questo? – salparadise

+0

"modello di progettazione migliore" - oh .. che tipo di motivo di progettazione è questo? :/ –

risposta

9

Non so di ottimizzazione per la velocità ma sono non un grande fan del if/return/else paradigma dato che intasa il codice con cose inutili e provoca scale indentazione per le lingue senza elif (non come un problema qui) .

Ottimizzazione per leggibilità (che di solito è la mia prima preferenza), mi piacerebbe girare tutte quelle elif righe in if e fosso il else del tutto, riformattare per renderlo più compatto:

def convert(data): 
    if isinstance(data, bytes): return data.decode('ascii') 
    if isinstance(data, dict): return dict(map(convert, data.items())) 
    if isinstance(data, tuple): return map(convert, data) 
    return data 
+0

Un tale semplice cambiamento per un così enorme miglioramento della leggibilità –

2

Estensione paxdiablo di risposta per gestire più casi d'uso ha portato a quanto segue:

def convert(data): 
    if isinstance(data, bytes):  return data.decode() 
    if isinstance(data, (str, int)): return str(data) 
    if isinstance(data, dict):  return dict(map(convert, data.items())) 
    if isinstance(data, tuple):  return tuple(map(convert, data)) 
    if isinstance(data, list):  return list(map(convert, data)) 
    if isinstance(data, set):  return set(map(convert, data)) 

Diventa chiaro che l'applicazione della funzione mappa è abbastanza coerente e possiamo generalizzarlo.

def convert(data): 
    data_type = type(data) 

    if data_type == bytes: return data.decode() 
    if data_type in (str, int): return str(data) 

    if data_type == dict: data = data.items() 
    return data_type(map(convert, data)) 
1

Il modo più semplice sarebbe quella di utilizzare comprensione dizionario come segue:

new_data = { key.decode(): val.decode() for key, val in data.items() } 

Esempio:

>>> data = { 
... b'cart1': b'apples', 
... b'cart2': b'oranges', 
... b'cart3': b'grapes' 
... } 
>>> 
>>> new_data = { key.decode(): val.decode() for key, val in data.items() } 
>>> 
>>> new_data 
{'cart1': 'apples', 'cart2': 'oranges', 'cart3': 'grapes'} 
>>> 

Per convertire coppie chiavi valore di tipo byte in ordine casuale, uso :

new_data = { 
    key.decode() if isinstance(key, bytes) else key: 
    val.decode() if isinstance(val, bytes) else val 
    for key, val in data.items() 
} 

Esempio:

>>> data = { 
... b'cart1': 'apples', 
... 'cart2': b'oranges', 
... b'cart3': b'grapes' 
... } 
>>> 
>>> new_data = { 
...  key.decode() if isinstance(key, bytes) else key: 
...  val.decode() if isinstance(val, bytes) else val 
...  for key, val in data.items() 
... } 
>>> new_data 
{'cart1': 'apples', 'cart2': 'oranges', 'cart3': 'grapes'} 
>>> 

Nota: Il codice di cui sopra sarà meglio per dizionario dei dati semplice. Ma per i dizionari complessi, io preferirei usare il codice Guy Gangemi s', che è una modifica del paxdiablo's risposta:

def convert(data): 
    if isinstance(data, bytes): return data.decode() 
    if isinstance(data, dict): return dict(map(convert, data.items())) 
    if isinstance(data, tuple): return tuple(map(convert, data)) 
    if isinstance(data, list): return list(map(convert, data)) 
    return data 

Esempio:

>>> 
>>> def convert(data): 
...  if isinstance(data, bytes): return data.decode() 
...  if isinstance(data, dict): return dict(map(convert, data.items())) 
...  if isinstance(data, tuple): return tuple(map(convert, data)) 
...  if isinstance(data, list): return list(map(convert, data)) 
...  return data 
... 
>>> 
>>> data = { 
...  b'fruits': { 
...    b'cart1': b'apples', 
...    b'cart2': 'oranges', 
...    b'cart3': b'grapes', 
...    b'cart4': (b'banana', 'pear'), 
...    b'cart5': [b'kiwi', b'papaya'] 
...  }, 
...  'vegetables': { 
...    'cart1': b'carrots', 
...    b'cart2': None, 
...    b'cart3': {}, 
...    b'cart4': False 
...  } 
... } 
>>> 
>>> convert(data) 
{'fruits': {'cart1': 'apples', 'cart2': 'oranges', 'cart3': 'grapes', 'cart4': ('banana', 'pear'), 'cart5': ['kiwi', 'papaya']}, 'vegetables': {'cart1': 'carrots', 'cart2': None, 'cart3': {}, 'cart4': False}} 
>>> 
Problemi correlati