Tengo una clase que contiene solo campos y no métodos, como este:
class Request(object):
def __init__(self, environ):
self.environ = environ
self.request_method = environ.get('REQUEST_METHOD', None)
self.url_scheme = environ.get('wsgi.url_scheme', None)
self.request_uri = wsgiref.util.request_uri(environ)
self.path = environ.get('PATH_INFO', None)
# ...
Esto podría traducirse fácilmente a un dict. La clase es más flexible para futuras adiciones y podría ser más rápida __slots__
. Entonces, ¿sería beneficioso usar un dictado en su lugar? ¿Un dictado sería más rápido que una clase? ¿Y más rápido que una clase con tragamonedas?
python
oop
class
dictionary
demonio
fuente
fuente
dict
puede tener sentido, a. gran ventaja: cuando depure, solo digaprint(request)
y verá fácilmente toda la información del estado. con el enfoque más clásico, tendrá que escribir sus__str__
métodos personalizados , lo que apesta si tiene que hacerlo todo el tiempo.Respuestas:
¿Por qué harías de esto un diccionario? Cual es la ventaja? ¿Qué sucede si luego desea agregar algún código? ¿A dónde iría tu
__init__
código?Las clases son para agrupar datos relacionados (y generalmente código).
Los diccionarios sirven para almacenar relaciones clave-valor, donde generalmente las claves son todas del mismo tipo y todos los valores también son de un tipo. Ocasionalmente, pueden ser útiles para agrupar datos cuando los nombres de clave / atributo no se conocen por adelantado, pero a menudo esto es una señal de que algo anda mal con su diseño.
Mantenga esto como una clase.
fuente
__init__
método de clase . Pero tienes razón: me separaría de las cosas que van juntas.where would your __init__ code go?
es preocupante. Podría persuadir a un desarrollador con menos experiencia de que solo se deben usar clases, ya que un método init no se usa en un diccionario. Absurdo.Utilice un diccionario a menos que necesite el mecanismo adicional de una clase. También puede utilizar un
namedtuple
enfoque híbrido:Las diferencias de rendimiento aquí serán mínimas, aunque me sorprendería que el diccionario no fuera más rápido.
fuente
Una clase en Python es un dictado debajo. Obtienes algo de sobrecarga con el comportamiento de la clase, pero no podrás notarlo sin un generador de perfiles. En este caso, creo que te beneficias de la clase porque:
fuente
Creo que el uso de cada uno es demasiado subjetivo para que pueda entrar en eso, así que me limitaré a los números.
Comparé el tiempo que lleva crear y cambiar una variable en un dict, una clase new_style y una clase new_style con ranuras.
Aquí está el código que utilicé para probarlo (está un poco desordenado pero funciona).
Y aquí está la salida ...
Creando ...
Cambiar una variable ...
Entonces, si solo está almacenando variables, necesita velocidad y no requerirá que haga muchos cálculos, le recomiendo usar un dictado (siempre puede hacer una función que parezca un método). Pero, si realmente necesita clases, recuerde: use siempre __ slots __ .
Nota:
Probé la 'Clase' con las clases new_style y old_style. Resulta que las clases old_style son más rápidas de crear pero más lentas de modificar (no mucho, pero sí significativas si estás creando muchas clases en un circuito cerrado (consejo: lo estás haciendo mal)).
Además, los tiempos para crear y cambiar variables pueden diferir en su computadora ya que la mía es vieja y lenta. Asegúrese de probarlo usted mismo para ver los resultados "reales".
Editar:
Más tarde probé la tupla con nombre: no puedo modificarla, pero para crear las 10000 muestras (o algo así) tomó 1,4 segundos, por lo que el diccionario es de hecho el más rápido.
Si cambio la función dict para incluir las claves y los valores y devolver el dict en lugar de la variable que contiene el dict cuando lo creo, me da 0,65 en lugar de 0,8 segundos.
Crear es como una clase con ranuras y cambiar la variable es lo más lento (0.17 segundos), así que no use estas clases . ir por un dict (velocidad) o por la clase derivada del objeto ('syntax candy')
fuente
dict
(sin métodos anulados, ¿supongo?). ¿Funciona de la misma manera que una clase de estilo nuevo que se escribió desde cero?Estoy de acuerdo con @adw. Nunca representaría un "objeto" (en un sentido orientado a objetos) con un diccionario. Los diccionarios agregan pares nombre / valor. Las clases representan objetos. He visto código donde los objetos se representan con diccionarios y no está claro cuál es la forma real de la cosa. ¿Qué sucede cuando ciertos nombres / valores no están ahí? Lo que impide que el cliente introduzca algo en absoluto. O intente sacar algo. La forma de la cosa siempre debe estar claramente definida.
Al usar Python, es importante construir con disciplina ya que el lenguaje permite que el autor se pegue un tiro en el pie de muchas formas.
fuente
Recomendaría una clase, ya que se trata de todo tipo de información relacionada con una solicitud. Si uno usara un diccionario, esperaría que los datos almacenados fueran de naturaleza mucho más similar. Una pauta que suelo seguir es que si quiero recorrer todo el conjunto de pares clave-> valor y hacer algo, uso un diccionario. De lo contrario, los datos aparentemente tienen mucha más estructura que un mapeo básico de clave-> valor, lo que significa que una clase probablemente sería una mejor alternativa.
Por lo tanto, quédese con la clase.
fuente
Si todo lo que desea lograr es sintaxis similar a dulces en
obj.bla = 5
lugar deobj['bla'] = 5
, especialmente si tiene que repetirlo mucho, tal vez desee usar alguna clase de contenedor simple como en la sugerencia de martineaus. Sin embargo, el código es bastante inflado e innecesariamente lento. Puedes hacerlo simple así:Otra razón para cambiar a
namedtuple
so una clase con__slots__
podría ser el uso de memoria. Los dictados requieren mucha más memoria que los tipos de listas, por lo que este podría ser un punto en el que pensar.De todos modos, en su caso específico, no parece haber ninguna motivación para alejarse de su implementación actual. No parece mantener millones de estos objetos, por lo que no se requieren tipos derivados de listas. Y en realidad contiene algo de lógica funcional dentro del
__init__
, por lo que tampoco deberías quedarte conAttrDict
.fuente
types.SimpleNamespace
(disponible desde Python 3.3) es una alternativa al AttrDict personalizado.Puede ser posible tener su pastel y comérselo también. En otras palabras, puede crear algo que proporcione la funcionalidad de una clase y una instancia de diccionario. Vea la receta Dɪᴄᴛɪᴏɴᴀʀʏ ᴡɪᴛʜ ᴀᴛᴛʀɪʙᴜᴛᴇ-sᴛʏʟᴇ ᴀᴄᴄᴇss de ActiveState y comentarios sobre las formas de hacerlo.
Si decides usar una clase normal en lugar de una subclase, he encontrado que la receta de Tʜᴇ sɪᴍᴘʟᴇ ʙᴜᴛ ʜᴀɴᴅʏ "ᴄᴏʟʟᴇᴄᴛᴏʀ ᴏғ ᴀ ʙᴜɴᴄʜ ᴏғ ɴᴀᴍᴇᴅ sᴛᴜғғ" ᴄʟᴀss (de Alex Martelli) es muy flexible y útil para el tipo de cosas que parece que lo estás haciendo (es decir, crea un agregador de información relativamente simple). Dado que es una clase, puede ampliar fácilmente su funcionalidad añadiendo métodos.
Por último, debe tenerse en cuenta que los nombres de los miembros de la clase deben ser identificadores legales de Python, pero las claves de diccionario no lo hacen, por lo que un diccionario proporcionaría una mayor libertad en ese sentido porque las claves pueden ser cualquier cosa que se pueda hash (incluso algo que no sea una cadena).
Actualizar
Una clase
object
(que no tiene una__dict__
) subclase nombradaSimpleNamespace
(que sí tiene una) se agregó altypes
módulo Python 3.3, y es otra alternativa.fuente
Recomiendo una clase. Si usa una clase, puede obtener una sugerencia de tipo como se muestra. Y el soporte de clase se completa automáticamente cuando la clase es un argumento de función.
fuente