J'ai une classe qui ne contient que des champs et aucune méthode, comme ceci:
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)
# ...
Cela pourrait facilement être traduit en dict. La classe est plus flexible pour les ajouts futurs et pourrait être rapide avec __slots__
. Y aurait-il donc un avantage à utiliser un dict à la place? Un dict serait-il plus rapide qu'une classe? Et plus rapide qu'une classe avec des machines à sous?
python
oop
class
dictionary
démon
la source
la source
dict
peut avoir un sens, vers. avantage: lorsque vous déboguez, dites simplementprint(request)
et vous verrez facilement toutes les informations d'état. avec l'approche plus classique, vous devrez écrire vos__str__
méthodes personnalisées , ce qui est nul si vous devez le faire tout le temps.Réponses:
Pourquoi voudriez-vous en faire un dictionnaire? Quel est l'avantage? Que se passe-t-il si vous souhaitez ajouter plus tard du code? Où irait votre
__init__
code?Les classes sont destinées à regrouper les données associées (et généralement le code).
Les dictionnaires servent à stocker les relations clé-valeur, où généralement les clés sont toutes du même type et toutes les valeurs sont également d'un même type. Parfois, ils peuvent être utiles pour regrouper des données lorsque les noms de clé / attribut ne sont pas tous connus à l'avance, mais cela indique souvent que quelque chose ne va pas avec votre conception.
Gardez cela une classe.
la source
__init__
méthode de classe . Mais vous avez raison: je séparerais des choses qui vont ensemble.where would your __init__ code go?
est préoccupante. Cela pourrait persuader un développeur moins expérimenté que seules les classes doivent être utilisées puisqu'une méthode init n'est pas utilisée dans un dictionnaire. Absurde.Utilisez un dictionnaire sauf si vous avez besoin du mécanisme supplémentaire d'une classe. Vous pouvez également utiliser a
namedtuple
pour une approche hybride:Les différences de performances ici seront minimes, même si je serais surpris si le dictionnaire n'était pas plus rapide.
la source
Une classe en python est un dict en dessous. Vous obtenez une surcharge avec le comportement de la classe, mais vous ne pourrez pas le remarquer sans un profileur. Dans ce cas, je pense que vous bénéficiez de la classe parce que:
la source
Je pense que l'utilisation de chacun est beaucoup trop subjective pour que je puisse entrer là-dessus, alors je vais m'en tenir aux chiffres.
J'ai comparé le temps nécessaire pour créer et changer une variable dans un dict, une classe new_style et une classe new_style avec des slots.
Voici le code que j'ai utilisé pour le tester (c'est un peu brouillon mais ça fait le travail.)
Et voici la sortie ...
Création ...
Changer une variable ...
Donc, si vous ne faites que stocker des variables, vous avez besoin de vitesse, et cela ne vous obligera pas à faire beaucoup de calculs, je vous recommande d'utiliser un dict (vous pouvez toujours créer une fonction qui ressemble à une méthode). Mais, si vous avez vraiment besoin de classes, rappelez-vous - utilisez toujours __ slots __ .
Remarque:
J'ai testé la «classe» avec les classes new_style et old_style. Il s'avère que les classes old_style sont plus rapides à créer mais plus lentes à modifier (pas de beaucoup mais significatives si vous créez beaucoup de classes dans une boucle serrée (astuce: vous le faites mal)).
Les temps de création et de modification des variables peuvent également différer sur votre ordinateur car le mien est ancien et lent. Assurez-vous de le tester vous-même pour voir les «vrais» résultats.
Éditer:
J'ai testé plus tard le namedtuple: je ne peux pas le modifier mais pour créer les 10000 échantillons (ou quelque chose comme ça), il a fallu 1,4 seconde, donc le dictionnaire est en effet le plus rapide.
Si je change la fonction dict pour inclure les clés et les valeurs et pour renvoyer le dict au lieu de la variable contenant le dict lorsque je le crée, cela me donne 0,65 au lieu de 0,8 seconde.
La création est comme une classe avec des slots et la modification de la variable est la plus lente (0,17 seconde) donc n'utilisez pas ces classes . optez pour un dict (speed) ou pour la classe dérivée de object ('syntax candy')
la source
dict
(sans méthodes remplacées, je suppose?). Fonctionne-t-elle de la même manière qu'une classe de style nouveau écrite à partir de zéro?Je suis d'accord avec @adw. Je ne représenterais jamais un "objet" (au sens OO) avec un dictionnaire. Les dictionnaires regroupent les paires nom / valeur. Les classes représentent des objets. J'ai vu du code où les objets sont représentés avec des dictionnaires et on ne sait pas quelle est la forme réelle de la chose. Que se passe-t-il lorsque certains noms / valeurs ne sont pas présents? Ce qui empêche le client de mettre quoi que ce soit. Ou d'essayer de faire sortir quoi que ce soit. La forme de la chose doit toujours être clairement définie.
Lorsque vous utilisez Python, il est important de construire avec discipline car le langage permet à l'auteur de se tirer une balle dans le pied de plusieurs façons.
la source
Je recommanderais une classe, car ce sont toutes sortes d'informations impliquées dans une demande. Si quelqu'un utilisait un dictionnaire, je m'attendrais à ce que les données stockées soient de nature beaucoup plus similaire. Une ligne directrice que j'ai tendance à suivre moi-même est que si je veux faire une boucle sur l'ensemble des paires clé-> valeur et faire quelque chose, j'utilise un dictionnaire. Sinon, les données ont apparemment beaucoup plus de structure qu'un mappage clé-> valeur de base, ce qui signifie qu'une classe serait probablement une meilleure alternative.
Par conséquent, restez avec la classe.
la source
Si tout ce que vous voulez obtenir est un bonbon de syntaxe
obj.bla = 5
au lieu deobj['bla'] = 5
, surtout si vous devez répéter cela beaucoup, vous voudrez peut-être utiliser une classe de conteneur simple comme dans la suggestion de martineaus. Néanmoins, le code y est assez gonflé et inutilement lent. Vous pouvez rester simple comme ça:Une autre raison de passer à
namedtuple
s ou à une classe avec__slots__
pourrait être l'utilisation de la mémoire. Les dictionnaires nécessitent beaucoup plus de mémoire que les types de liste, donc cela pourrait être un point à considérer.Quoi qu'il en soit, dans votre cas spécifique, il ne semble pas y avoir de motivation pour abandonner votre implémentation actuelle. Vous ne semblez pas gérer des millions de ces objets, donc aucun type dérivé de liste n'est requis. Et il contient en fait une logique fonctionnelle dans le
__init__
, donc vous ne devriez pas non plus vous y mettreAttrDict
.la source
types.SimpleNamespace
(disponible depuis Python 3.3) est une alternative au AttrDict personnalisé.Il est peut-être possible d'avoir votre gâteau et de le manger aussi. En d'autres termes, vous pouvez créer quelque chose qui fournit les fonctionnalités d'une classe et d'une instance de dictionnaire. Voir la recette Dɪᴄᴛɪᴏɴᴀʀʏ ᴡɪᴛʜ ᴀᴛᴛʀɪʙᴜᴛᴇ-sᴛʏʟᴇ ᴀᴄᴄᴇss d'ActiveState et des commentaires sur les moyens de le faire.
Si vous décidez d'utiliser une classe régulière plutôt qu'une sous-classe, j'ai trouvé que la recette Tʜᴇ sɪᴍᴘʟᴇ ʙᴜᴛ ʜᴀɴᴅʏ "ᴄᴏʟʟᴇᴄᴛᴏʀ ᴏғ ᴀ ʙᴜɴᴄʜ ᴏғ ɴᴀᴍᴇᴅ sᴛᴜғғ" ᴄʟᴀss (par Alex Martelli) est très flexible et utile pour le genre de chose qu'elle ressemble à ce que vous faites (c'est-à-dire créer un agrégateur d'informations relativement simple). Puisqu'il s'agit d'une classe, vous pouvez facilement étendre ses fonctionnalités en ajoutant des méthodes.
Enfin, il convient de noter que les noms des membres de la classe doivent être des identificateurs Python légaux, mais pas les clés de dictionnaire - un dictionnaire offrirait donc une plus grande liberté à cet égard car les clés peuvent être tout ce qui peut être haché (même quelque chose qui n'est pas une chaîne).
Mettre à jour
Une classe
object
(qui n'a pas de__dict__
) sous-classe nomméeSimpleNamespace
(qui en a une) a été ajoutée autypes
module Python 3.3, et est encore une autre alternative.la source
Je recommande une classe. Si vous utilisez une classe, vous pouvez obtenir une indication de type comme indiqué. Et la classe prend en charge la complétion automatique lorsque la classe est l'argument de la fonction.
la source