python - lenguaje - ¿Por qué la lista no tiene un método seguro de "obtener" como el diccionario?
python tutorial (10)
>>> d = {''a'':''b''}
>>> d[''a'']
''b''
>>> d[''c'']
KeyError: ''c''
>>> d.get(''c'', ''fail'')
''fail''
>>> l = [1]
>>> l[10]
IndexError: list index out of range
Así que investigué un poco más sobre esto y resulta que no hay nada específico para esto. Me entusiasmé cuando encontré list.index (value), devuelve el índice de un elemento especificado, pero no hay nada para obtener el valor en un índice específico. Entonces, si no quieres usar la solución safe_list_get, creo que es bastante buena. Aquí hay algunas frases de 1 línea si pueden hacer el trabajo por usted según el escenario:
>>> x = [1, 2, 3]
>>> el = x[4] if len(x) == 4 else ''No''
>>> el
''No''
También puede usar None en lugar de ''No'', que tiene más sentido .:
>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None
Además, si solo quiere obtener el primer o el último elemento de la lista, esto funciona
end_el = x[-1] if x else None
También puede convertirlos en funciones, pero aún así me gustó la solución de excepción IndexError. Experimenté con una versión safe_list_get
solución safe_list_get
y la hice un poco más simple (sin valor predeterminado):
def list_get(l, i):
try:
return l[i]
except IndexError:
return None
No ha realizado una evaluación comparativa para ver qué es lo más rápido.
Créditos a jose.angel.jimenez
Para los fanáticos del "oneliner" ...
Si desea el primer elemento de una lista o si desea un valor predeterminado si la lista está vacía, intente:
liste = [''a'', ''b'', ''c'']
value = (liste[0:1] or (''default'',))[0]
print(value)
devuelve a
y
liste = []
value = (liste[0:1] or (''default'',))[0]
print(value)
devuelve por default
Ejemplos de otros elementos ...
liste = [''a'', ''b'', ''c'']
print(liste[0:1]) # returns [''a'']
print(liste[1:2]) # returns [''b'']
print(liste[2:3]) # returns [''c'']
Con el retorno predeterminado ...
liste = [''a'', ''b'', ''c'']
print((liste[0:1] or (''default'',))[0]) # returns a
print((liste[1:2] or (''default'',))[0]) # returns b
print((liste[2:3] or (''default'',))[0]) # returns c
Probado con Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
En última instancia, probablemente no tenga un método .get
seguro porque un dict
es una colección asociativa (los valores están asociados a nombres) donde es ineficiente verificar si una clave está presente (y devolver su valor) sin lanzar una excepción, mientras que es súper trivial para evitar excepciones al acceder a los elementos de la lista (ya que el método len
es muy rápido). El método .get
permite consultar el valor asociado con un nombre, no acceder directamente al 37º elemento en el diccionario (que sería más parecido a lo que está pidiendo de su lista).
Por supuesto, puede implementarlo usted mismo fácilmente:
def safe_list_get (l, idx, default):
try:
return l[idx]
except IndexError:
return default
Incluso podrías ponerlo en parche en __builtins__.list
constructor en __main__
, pero eso sería un cambio menos generalizado ya que la mayoría del código no lo usa. Si solo quisiera usar esto con listas creadas por su propio código, podría simplemente crear una list
subclase y agregar el método get
.
En lugar de usar .get, usar esto debería estar bien para las listas. Solo una diferencia de uso.
>>> l = [1]
>>> l[10] if 10 < len(l) else ''fail''
''fail''
Esto funciona si quieres el primer elemento, como my_list.get(0)
>>> my_list = [1,2,3]
>>> next(iter(my_list), ''fail'')
1
>>> my_list = []
>>> next(iter(my_list), ''fail'')
''fail''
Sé que no es exactamente lo que pediste, pero podría ayudar a otros.
Lo mejor que puedes hacer es convertir la lista en un dict y luego acceder a ella con el método get:
>>> my_list = [''a'', ''b'', ''c'', ''d'', ''e'']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: ''a'', 1: ''b'', 2: ''c'', 3: ''d'', 4: ''e''}
>>> my_dict.get(2)
''c''
>>> my_dict.get(10, ''N/A'')
Los diccionarios son para búsquedas. Tiene sentido preguntar si existe una entrada o no. Las listas suelen ser iteradas. No es común preguntar si L [10] existe, sino más bien si la longitud de L es 11.
Probablemente porque simplemente no tenía mucho sentido para la semántica de la lista. Sin embargo, puede crear fácilmente los suyos creando subclases.
class safelist(list):
def get(self, index, default=None):
try:
return self.__getitem__(index)
except IndexError:
return default
def _test():
l = safelist(range(10))
print l.get(20, "oops")
if __name__ == "__main__":
_test()
Prueba esto:
>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), ''fail'')
4
>>> next(iter(a[i + 1:]), ''fail'')
''fail''
Su caso de uso básicamente solo es relevante para cuando se hacen matrices y matrices de una longitud fija, para que sepa cuánto tiempo están antes de la mano. En ese caso, normalmente también los crea antes de llenarlos manualmente con Ninguno o 0, de modo que, de hecho, ya existe el índice que usará.
Podrías decir esto: necesito .get () en los diccionarios con bastante frecuencia. Después de diez años como programador de tiempo completo, no creo haberlo necesitado nunca en una lista. :)