J'ai un moyen de construire une structure de données (hors du contenu de fichier, disons):
class lazyload: def __init__(self,FILE): self.FILE = FILE def __getattr__(self,name): self = loadfile(self.FILE) # this never gets called again # since self is no longer a # lazyload instance return object.__getattribute__(self, name)
6 Réponses :
Le module CSV dans le STDLibrary Python ne chargera pas les données tant que vous ne commencerez pas l'itération dessus, il est donc en fait paresseux.
Edit: Si vous devez lire via l'ensemble du fichier pour construire le DataStructure, avoir un Objet de chargement paresseux complexe que les objets de proxie sont surchargés. Il suffit de faire ceci: p> avec la classe ci-dessus, vous pouvez le faire: p> aussi p> allkitties = kitties.get_data() # wait
print len(allkitties)
print kitties[32]
Je ne traite pas réellement de fichiers csv code>; C'était juste à des fins d'illustration. Mais c'est bon à savoir. De plus,
loadfile code> devra itérer sur les données s'il s'agit de créer une structure de données non standard intéressante, de sorte que la paresse de
csv code> peut ne pas suffire.
Si je comprends bien, votre self._data code> est exactement analogue à mon
auto.f code> et votre
_build_data code> est exactement analogue à mon
Loadfile code>. La bonne chose à propos de l'utilisation
__ getattr __ code> est que vous n'avez pas à écrire
.get_data () code> partout; Vous pouvez interagir avec le wrapper exactement i> comme vous le feriez avec la structure de données directement.
Ouais, mais alors vous avez besoin de plus que __ getattr __ code>, vraiment, vous devez écrire un proxy complet, et cela ne vaut pas la peine. Simple = bon. Et vous n'avez pas à écrire Get_Data () partout. Vous venez d'écrire des données = thewrapper.get_data (), vous ne l'écrivez donc qu'une seule fois pour chaque fonction où vous devez accéder aux données.
N'écrireait pas data = thewrapper.get_data () code> vaincre le but du chargement paresseux? Pourquoi
__ getattr __ code> pas assez en principe?
Non, cela ne vaincrait pas le but. Il chargerait les données, alors appellerait GetTATTR B>. Dans les deux cas, toutes les données sont chargées la première fois que vous le souhaitez.
ne serait pas __ getattr __ code>, vous mettant une boucle infinie? Je pense que votre approche a du sens, mais d'être du côté sûr, je ferais cette ligne dans:
if name == "F" and not self.F:
__ getattr __ code> est seulement appelé si la méthode n'est pas trouvée ( docs.python.org/py3k/reference/... ), donc je ne pense pas que ce soit un problème.
@Anton: Merci, je ne savais pas cela auparavant. Je laisserai cette réponse afin que d'autres personnes puissent voir cette information.
Voici un piratage qui rend le travail de solution «encore meilleur», mais je pense que c'est assez ennuyant qu'il est probablement préférable d'utiliser la première solution. L'idée est d'exécuter l'étape alors vous pouvez faire P > self = loaderfile (self.file) code> en passant le nom de la variable en tant qu'attribut:
kitties = lazyload("kitties.csv","kitties")
^ ^
\ /
These two better match exactly
Je sais que vous venez probablement de jeter des idées, mais ce genre de chose devrait vraiment être découragé. En plus de la méchanceté que vous avez signalé vous-même, cela ne fonctionnera que tant que l'objet doit seulement être mentionné par un seul nom global. Attribuez-le à un autre nom et travaillez à ce sujet, et les chatons sont rechargées et remplacées après chaque accès d'attribut. Passez-le à une fonction et chaque utilisation de l'objet dans la fonction le fera de recharger.
Si vous avez besoin d'une utilisation Je mettant en œuvre la charge paresseuse pour mes besoins, il existe un code non adapté: p> (maître est un objet de registre qui charge des données lorsque je exécute sa méthode get () > Cette implémentation fonctionne bien pour Isinstance () et Str () et JSON.Dumps () avec IT P> P> chiots [32] code> Vous devez également définir
__ getItem __ code> méthode car
__ getattr __ code> ne pas attraper ce comportement.
Pour autant que je sache, cette affirmation est incorrecte: "Si vous avez besoin d'utiliser chiots [32] code> Vous devez également définir
__ getItem __ code> car
__ getattr __ < / Code> Ne pas attraper ce comportement. " I> J'ai réellement testé le code dans la question et c'est fait i> travail. Cependant, il est vrai que
__ getattribute __ code> n'atteigne pas
__ getItem __ code>.
Si vous êtes vraiment inquiet à propos de la déclaration IF, vous avez un objet STRAND> STARTFIVE STRAND>.
class LoadMe( object ): def __init__( self, parent ): self.parent= parent def load( self ): ## Actually load, setting self.parent.data return DoneLoading( self.parent ) class DoneLoading( object ): def __init__( self, parent ): self.parent= parent def load( self ): return self
Je ne comprends pas cette réponse (encore?). Il semble que, une fois que l'objet est effectivement chargé, les seules méthodes disponibles sont obtenez code> et
mettre code>. Mais il y a beaucoup d'autres moyens de pouvoir interagir avec la structure de données. Par exemple,
chiots [34] code> et
len (chiots) code> serait chacun lancer un
attributeError code> à l'aide de cette méthode, non?
@Anton Geraschenko: "Mais il y a beaucoup d'autres moyens de pouvoir interagir avec la structure de données". Bon. Écrire plus de méthodes. Je ne pouvais que penser à deux. Vous pouvez penser à plus. Écrire plus.
Merci de clarifier. Maintenant, je comprends la réponse, mais c'est strictement pire que la solution que j'ai proposée dans la question, qui fait chaque méthode i> disponible pour une structure de données imaginable i>. __ getattr __ code> est une méthode de capture qui fait de longues listes de définitions de méthodes presque identiques inutiles.
@Anton Geraschenko: "Mais c'est strictement pire que la solution que j'ai proposée". Êtes-vous incapable de fusionner les deux? Je penserais que vous pouvez utiliser un conception Etat B> pour éliminer la déclaration IF, couplée à votre __ getattr __ code>-Based. Je suis tout à fait sûr que les réponses ne sont pas des propositions de toutes ou de rien, mais plus comme des suggestions ou des allusions.
Ah, je pense que je comprends mieux maintenant, même si je ne comprends toujours pas pourquoi vous voulez éliminer le si code>. Je suppose que c'est juste au cas où la structure de données est
Aucun code> ou pour enregistrer l'heure de test si quelque chose est
Aucun code> (?). La raison pour laquelle je pensais que le code (ne fonctionne pas) dans la question serait "encore meilleur", c'est qu'après chargé de la structure de données, l'objet serait complètement indiscernable i> d'un objet chargé directement, en bas au point que ce ne serait plus une instance de la classe wrapper.
@Anton Geraschenko: Cet objet serait complètement indiscernable. La classe "Wrapper" est l'objet correspondant. Pas de changement. La seule chose qui change est un état interne invisible à l'API.
L'objet serait en grande partie i> indiscernable, mais pas complètement. Le wrapper est une instance de luisyload code>, mais si elle est chargée directement, ce serait une instance de
dict code> (ou autre). Le wrapper a
source code> et
attributs code>, que la structure de données ne le fait pas. Ceci est normalement hors de propos, mais note dans le Solution que j'ai donnée , après que l'enveloppe soit appelée une fois, il cesse être un wrapper i>. Il devient la structure de données directement, de la même manière que votre document code> arrête d'être un
loadme code> et devient un
DonLoading code>.
Bien sûr, cette solution me demande également de transmettre le nom de la variable comme un argument et suppose implicitement qu'il est global. Il serait plus agréable s'il y avait un moyen de réaffecter directement auto code> dans une méthode.
@Anton Geraschenko: "Nécessite que je passe le nom de la variable comme argument"? Comment __ getattr __ code> nécessite-t-il? Je pensais que
__ getattr __ code> a donné accès aux variables sans utiliser le nom comme argument à une méthode. Qu'est-ce que je rate?
@Anton Geraschenko: "L'emballage est une instance de lazyload, mais si elle est chargée directement, ce serait une instance de dict (ou autre)." Faux et faux. Tout d'abord, LAZYLOID code> peut être une sous-classe de
dict code>. Deuxièmement, une "charge directe" n'a pas de sens. Une fois que vous avez un chargeur paresseux, vous n'utiliseriez jamais rien d'autre. De plus, si vous voulez que votre "loader paresseux" soit l'objet d'application, c'est trivial. Le chargement paresseux n'est qu'une caractéristique de l'objet d'application. Puisque vous avez fourni zéro orientation sur ce que vous voulez cela d'autre, je ne peux pas prévoir toutes les fonctionnalités de l'application que vous souhaitez. Ajoutez-les vous-même s'il vous plaît.
Il semble que nous ayons de graves difficultés à communiquer. Je ne vois pas à vous ou que vous ne voyez pas pourquoi personne voudrait une classe de chargeuse paresseuse que l'agnostique sur quelle structure de données il chargée et est complètement fidèle (en ce sens qu'elle se comporte exactement comme la structure de données qu'elle charge de chargement, Mais a aucune caractéristique de son propre i>). Désolé de gaspiller votre temps (et mon) temps.
@Anton Geraschenko: "Agnostic sur quelle structure de données il est en cours de chargement" est absurde. Vous ne pouvez pas être «agnostique» sur la classe chargée. Sauf si vous avez quelque chose d'autre à l'esprit que vous ne mettez pas dans la question. Mettez à jour la question b> pour contenir tout b> de vos besoins.
Voici une solution qui utilise un décorateur de classe pour différer l'initialisation jusqu'à la première utilisation d'un objet:
kittens is instance of FileLoader: True Performing expensive load operation 2 Felix Eeek kitties.csv kitties.csv
Vous voudrez peut-être proxy
__ non zéro __ code> et d'autres méthodes également.
@ephemient: il ressemble à un appel à
__ non nulo __ code> passera par
__ getattr __ code>, alors quel est le problème?
Je suppose que c'est un peu mieux de dire
si self.f n'est pas Aucun code> plutôt que
si non auto.f code> depuis
loaderfile (fichier) code> < I> pourrait i> 0 ou la chaîne vide.
Hein, je pensais que ça ne l'a pas fait. Eh bien, peut-être que vous ne le faites pas.
Mise à jour de ma réponse, reflétant votre commentaire.