sintaxis - lambda python 3 español
¿La ventaja de usar una lambda: ninguna función como espacio de nombres? (2)
Vi el siguiente code :
eris = lambda:None
eris.jkcpp = np.einsum(''iipq->ipq'', eriaa[:ncore[0],:ncore[0],:,:])
eris.jc_PP = np.einsum(''iipq->pq'', eriab[:ncore[0],:ncore[0],:,:])
¿Podemos definir atributos arbitrarios para una función definida por lambda:None
?
Estaba leyendo un código casscf, que es un algoritmo en química cuántica, y el autor usó esta función lambda para obtener las integrales de 2 electrones. Y luego code , al parecer.
¿Cuál es la ventaja de usar una función lambda: Ninguna?
Que está pasando aqui
eris = lambda:None
eris.jkcpp = ...
es que el escritor está creando un espacio de nombres utilizando un objeto de función para su __dict__
.
Un espacio de nombres es un dominio donde los nombres legales de Python se asignan a objetos, y cuando hace algo como lo anterior, la ventaja de un espacio de nombres es que los nombres no están en el ámbito local y global, donde podrían sobrescribirse o sobrescribirse en los mismos nombres están destinados a apuntar a diferentes objetos.
No hay nada de malo en esto a primera vista, pero si otros intentan leer el código para comprender qué está sucediendo con esta función que se está transmitiendo, entonces probablemente estén pensando:
¿Alguna vez será llamado? ¿Por qué estamos pasando alrededor de un grito? Un llamador que devuelve Ninguno no es muy útil, esto debe ser algún tipo de pirateo.
Para evitar confusiones, use un objeto que se entenderá semánticamente como un espacio de nombres.
Espacios de nombres
Tenemos un objeto SimpleNamespace en la biblioteca estándar de Python 3:
from types import SimpleNamespace
eris = SimpleNamespace()
eris.jkcpp = ...
En Python 2, sería común hacer algo como:
class NS(object):
pass
eris = NS()
eris.jkcpp = ...
Si necesita un espacio de nombres simple, estas son opciones correctas.
Desventajas
Sin embargo, todavía tengo que usar estas formas de espacios de nombres. O bien me parece que un grupo con nombre sería suficiente para que la semántica se lleve con los datos (particularmente útil cuando hay muchos de ellos) o uso un objeto mutable con algo más que simplemente pass
.
Como son, realmente no son diferentes, programáticamente, de un diccionario simple. Los valores a los que apuntan los nombres se almacenan en el __dict__
del objeto. Usted también puede estar pasando alrededor de una instancia de dict
. La búsqueda de puntos agrega un poco de sobrecarga (se verifica para ver si el tipo del objeto tiene descriptores de datos antes de buscar en el diccionario del objeto) también.
Conclusión:
La instancia de espacio de nombres puede tener algunas desventajas, pero puede ser más legible. La legibilidad cuenta. Si crees que tu programa necesita un espacio de nombres simple, úsalo.
Pero no use una función de no hacer nada para un espacio de nombres. Es engañoso y no tendrá sentido para nadie.
Esto parece un truco para crear un objeto simple para mantener los valores en una línea. La mayoría de los objetos incorporados no le permiten establecer atributos arbitrarios en ellos:
>>> object().x = 0
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: ''object'' object has no attribute ''x''
>>> ''''.x = 0
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: ''str'' object has no attribute ''x''
>>> [].x = 0
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: ''list'' object has no attribute ''x''
Si crea su propia clase, entonces puede agregar los atributos que desee. En este caso, podría crear una clase cuyo método __init__
asigne los atributos, pero puede que esto no valga la pena. Así que puedes hacer una clase vacía:
>>> class Data(object): pass
>>> d = Data()
>>> d.x = 0
>>> d.x
0
Al parecer, el programador no está al tanto de esto o no quiere esa línea adicional donde se declara la clase y ha creado su propia solución para almacenar datos. Resulta que las funciones, a pesar de ser un tipo incorporado , le permiten agregar atributos a ellas:
>>> def foo(): pass
>>> foo.x = 0
>>> foo.x
0
Tanto lo anterior como la lambda le permiten crear dicho contenedor en una sola declaración. En realidad creo que es una buena idea.