J'ai besoin d'un objet ressemblant à une liste qui "autogrow" lorsque un numéro de créneau est accessible ou égal à sa longueur, remplissez toutes les machines à sous nouvellement créées avec une valeur par défaut pré-spécifiée. E.G.:
# hypothetical DefaultList class x = DefaultList(list('abc'), default='*') x[6] = 'g' print x[2], x[4], x[6], x[8] # should print 'c * g *'
--p>Manks!
>> Je sais qu'il n'est pas difficile de mettre en œuvre une classe comme celle-ci, mais j'évite la réinvention de la roue autant que possible, surtout si une roue particulièrement efficace / bien conçue existe déjà. P>
ps2. Un dict (ou une collection de collections.default) est pas em> une implémentation acceptable de la structure de données souhaitée. Pour pourquoi, voir ici: http://groups.google .com / groupe / comp.lang.python / msg / bcf360dfe8e868d1? hl = fr p> p>
5 Réponses :
J'utiliserais un Structure de données SPARSE (matrice 1xn). p>
N'est-ce pas juste un dictionnaire enveloppé dans une API de tableau?
Il existe plusieurs implémentations: avec différentes stratégies de stockage.
Stackoverflow.com/Questtions/1857780/... est aussi un bon exemple
Vous pouvez toujours faire une fonction qui gère ceci:
def fillList(item, slot, myList): length = len(myList) if slot > length: augmentation = [item for x in range(slot-length)] myList.extend(augmentation) else: myList[slot] = item
Utilisation de l'idée de la solution de Wheatie et de la création d'une interface plus jolie:
Vous pouvez hériter de la liste et écraser la liste " getItem strong> (index)" méthode qui plante dans votre classe. . Il devrait être quelque chose comme ceci: p> Ce même code peut être utilisé si vous n'allez pas la liste, mais vous renvoyez simplement une valeur par défaut sur Index non valide P> Cela préserve toute l'interface de la liste. p> p>
Je ne sais pas si c'est plus efficace, mais votre compréhension de la liste pourrait être réécrite comme queue = [auto.default_value] * (indice-longueur + 1) code>.
class DefaultList(list): def __init__(self,*args,**kwargs): list.__init__(self,*args) self.default=kwargs.get('default',None) def __getitem__(self,key): # retrieving an item does not expand the list if isinstance(key,slice): return [self[elt] for elt in range(key.start,key.stop,key.step)] else: try: return list.__getitem__(self,key) except IndexError: return self.default def __setitem__(self,key,value): # setting an item may expand the list try: list.__setitem__(self,key,value) except IndexError: self.extend([self.default]*(key-len(self))) self.append(value) x = DefaultList(list('abc'), default='*') print(x) # ['a', 'b', 'c'] x[6] = 'g' print(x) # ['a', 'b', 'c', '*', '*', '*', 'g'] print x[2], x[4], x[6], x[8] # should print 'c * g *' # c * g * print(x[2:9:2]) # ['c', '*', 'g', '*']
Ceci est raisonnable; Un couple notes. Vous devez utiliser Super code> plutôt que de traiter directement la classe mère.
Aucun CODE> est probablement un
FLIDVALUE CODE> plus sensé que
'*' code>. Vous devriez passer
kwargs code> à
list .__ init __ code>, donc les arguments de mots clés fonctionnent, par exemple.
LIMITELLLIST (Séquence = [1,2,3]) Code>.
@Glenn Maynard: Je pense qu'utiliser super code> ici conduirait à un piège subtil. Étant donné que
parluministe code> 's
__ init __ code> Signature est différent de la liste code> code>' S
__ init __ code>, je ne peux pas utiliser
Super code>.
Super (defaultlist, Self) .__ init __ (* args, ** kwargs) Code> Souleverait un typeError depuis
Liste .__ init __ code> attend au plus 1 argument. J'aime l'idée d'utiliser
Aucun code> comme défaut.
(Ce n'est pas lié à Super code>.) Vous souhaitez effectuer une copie de kwargs (
kwargs = dict (kwargs) code>) et supprimez "par défaut" s'il existe après avoir tiré le Valeur dehors. De cette façon, il est aussi transparent que possible avec des arguments, de sorte que les choses ne vont pas mal si cette classe est utilisée avec un héritage plus complexe. (Il est plus simple de simplement faire
par défaut code> un argument de mot clé régulier, mais qui ne peut être effectué que correctement dans Python3, qui prend en charge les arguments mot-clé uniquement via PEP 3102.)
@Glenn Maynard: Dans un schéma d'héritage plus complexe, si une autre classe s'attend à ce que mot-clé code> par défaut code>, en le supprimant dans list code> serait faux. Puisque nous ne savons pas que
__ code> est appelé par
super (LIMITEDLLIST, auto) .__ init __ code>, la seule option sûre est d'exiger tout
__ init__ code> Les signatures correspondent exactement. Donc, la seule option sûre est de (avoir un mot clé code> par défaut et utiliser
list .__ init __ code>) ou (supprimer le mot-clé code> Utilisez
Super code> si vous le souhaitez).
Si vous héritez de deux classes qui ont leur propre par défaut code> par défaut à
__ init __ code>, tout est perdu; ça ne va pas fonctionner. Votre code toujours i> pause si une autre classe héritée a besoin de kwargs. La bonne chose à faire est de prendre les paramètres spécifiques à votre fonction et de les supprimer de Kwargs et de passer le reste sur. (Je ne sais pas pourquoi vous continuez à dire
Super code>;
super .__ init __ (...) code> et
liste .__ init __ (auto, ...) code> dans votre code équivalent, à l'exception de l'ancien se comportera dans des scénarios complexes MI où ce dernier se cassera.)
@Glenn Maynard: Vous semblez coder pour une flexibilité maximale, je code pour Yagni ( FR. wikipedia.org/wiki/you_ain%27t_gonna_neeed_it ). Devrions-nous convenir que les deux objectifs sont importants et que la bonne réponse dépend donc des besoins de l'OP qui n'a aucun de nous vraiment?
Non, vous avez épandré de mauvaises habitudes aux autres en montrant du code comme celui-ci. Vous n'utilisez pas seulement super code> lorsque vous pensez qu'il est important; Vous devriez l'utiliser par défaut, tout le temps, sans y penser à deux fois. C'est ainsi que les méthodes de base sont appelées en python, non par la référencement directement de la méthode.
@Glenn Maynard: Si vous Google "Glenn Maynard Class Site: Stackoverflow.com" Vous trouverez de nombreux exemples de classes qui manquent d'appel à Super code>. Si vous voulez vraiment utiliser Super partout, même des classes qui hériter de
objet code> doivent appeler
super code> dans
__ init __ code>. S'il vous plaît pratiquer ce que vous prêchez.
Ne pas appeler la base __ init __ code> pour les classes dérivant de
objet code> n'est peut-être pas une pratique idéale, mais c'est une pratique idiomatique définitive. Appeler des méthodes de base directement comme vous êtes pas i>; C'est faux et la fixant à suivre le modèle de données Python et Python Idiom est trivial: une modification d'une ligne pour chaque
list.func code>. Je ne sais pas pourquoi vous essayez si fort de justifier de ne pas résoudre une simple erreur qui mènera les autres aux mauvaises habitudes.
Être un Stackoverflow noob, j'ai accepté cette réponse comme une réponse, même si ce n'est pas meilleur que ce que je pouvais coder moi-même (en fait, je peux penser à de nombreux aspects de la mise en œuvre que je préférerais faire différemment). J'ai expressément déclaré que j'étais intéressé par quelque chose de préexistant (et probablement bien testé) plutôt que d'une implémentation rapide et exclusive ... La prochaine fois que je vais faire ce point encore plus clair.
Tous les classes n'ont pas besoin d'être multi-héritage amical et super () code> a ses propres problèmes. Il appartient au programmeur de penser au problème, à l'utilisation et à décider de ce qui est approprié.
@unutbu Votre __ getItem __ code> ne vérifie pas les limites. La liste ne devrait augmenter que sur
__ settitem __ code>, mais il est efficacement de longueur infinie comme vous l'avez maintenant.
@Sethan Furman: __ getItem __ code> ne vérifie pas les limites car
Listlist code> est censé "autogrow". Voyez-vous un problème avec cela que je suis surveillé?
@unutbu ma compréhension était i> autogrow sur le réglage, pas regarder. Relire les spécifications de l'OP, cependant, je vois que j'avais tort. Cela signifie que des soins supplémentaires devraient être pris pour autoriser itérant, ou pour l'élément dans autogroding_list: do_something_with (élément) code> serait une boucle infinie.
(Ce n'est pas une nouvelle réponse; juste un commentaire sur tsutbu. Il devrait vraiment être possible de poster des choses comme celle-ci dans des commentaires; ce n'est pas, alors je dois le poster comme une réponse.)
Il s'agit de toutes les pratiques standard dans le modèle de données de Python; Vous ne devriez presque jamais appeler une méthode de classe de base directement plutôt que via Notez que dans Python 3, ceci est supporté par la langue. directement: p> mais ce n'est pas pris en charge dans Python 2. http://www.python.org/dev/peps/pep-3102 p> p> CombinelistClasses Code> et
CombinelistClasses2 Code> hérit de deux classes qui héritent de code> code>. Le comportement et les doctests sont simples, mais brisent mal dans la version originale. P>
super code>. p>
Cet article est assez vieux, je ne peux pas obtenir une réponse ici, mais existe-t-il une raison pour ne pas approcher de la manipulation par défaut comme: self.default = kwargs.pop ('défaut', aucun) code>? Je crois que cela accomplit la même chose que votre déclaration conditionnelle avec 4 lignes de code moins importantes, mais je suis plus intéressé dans la pratique appropriée que le nombre de lignes. S'il y a une raison de ne pas utiliser
.pop (
@ g.d.d.c. En utilisant kwargs.pop (mot-clé, aucun) code> va bien et est la solution plus pythonique
Donc, si quelqu'un crée une nouvelle collection, place quelque chose dans Slot 1 puis dans la fente 1 000 000, vous vous retrouvez avec 999 998 objets inutiles qui prennent la mémoire? Cela ressemble à une mauvaise idée pour moi.
Peut-être que cela suffirait, si vous conservez vos articles ajoutés en dict, et de conserver la valeur par défaut - les membres non modifiés ne doivent pas nécessairement être conservés dans la mémoire.
Corrigez-moi si je me trompe, mais étant donné que votre lien n'est pas votre problème plus avec l'interface de collections.defaultdict plutôt qu'utilise plutôt une comme une mise en œuvre?
Je ne vois pas d'argument contre l'utilisation de
dict code> S comme backend dans le lien - tant que l'interface est
Liste () Code> Compatible, pourquoi est-ce important?