6
votes

Numpy.ndarray: Conversion d'une classe "normale"

[python 3]

J'aime ndarray mais je trouve cela ennuyeux d'utiliser.

Voici un problème que je suis confronté. Je veux écrire un tableau qui héritera d'une grande partie de la fonctionnalité de Ndarray, mais n'a qu'un seul moyen d'être instancié: comme une matrice remplie zéro d'une certaine taille. J'espérais écrire: xxx

J'aimerais appeler super () .__ init __ avec quelques paramètres pour créer une matrice remplie de zéro, Mais cela ne fonctionnera pas car ndarray utilise une fonction globale numpy.zeros (plutôt qu'un constructeur) pour créer un tableau rempli de zéro.

Questions:

  1. Pourquoi Ndarray utilise-t-il des fonctions globales (module) au lieu de constructeurs dans de nombreux cas? C'est une grosse ennui si j'essaie de les réutiliser dans un cadre orienté objet.

  2. Quelle est la meilleure façon de définir tableau de classe dont j'ai besoin? Devrais-je simplement remplir manuellement ndarray avec des zéros ou y at-il un moyen de réutiliser la fonction zeros ?


3 commentaires

Je ne vois pas pourquoi vous voulez créer votre propre cours du tout. Quel est l'avantage sur le numpy.zeros () fonction d'usine? Si vous n'aimez pas le nom, il suffit de le renommer, comme Create_array = numpy.zeros .


Je ne suis plus sûr qu'il y ait un avantage. Peut-être que je ne suis tout simplement pas habitué à la fonction d'usine. Je vais devoir y penser.


@Sven Marnach: J'ai trouvé plusieurs liens sur ce sujet général: Stackoverflow.com / Questions / 628950 / ... Stackoverflow.com/Questions/ 2959871 / ... Stackoverflow.com/questions/4617311/... Rien de particulier à Python, mais les commentaires généraux d'autres langues semblent appliquer. Et autant que je sache, il n'y a vraiment pas d'inconvénient pour les fonctions d'usine (autres que ma préférence personnelle).


3 Réponses :


8
votes

Pourquoi Ndarray utilise-t-il des fonctions globales (module) au lieu de constructeurs dans de nombreux cas?

  1. Pour être compatible / similaire à Matlab, où des fonctions telles que zeros ou sont originaires de.
  2. Les fonctions d'usine globales sont rapides à écrire et à comprendre. Quelle devrait être la sémantique d'un constructeur, par ex. Comment afficheriez-vous un simple zeros ou vide ou ou avec un seul constructeur? En fait, ces fonctions d'usine sont assez courantes, également dans d'autres langages de programmation.

    Quelle est la meilleure façon de définir le tableau que j'ai besoin? xxx

    Notez que c'est Python 2, mais il ne nécessiterait que de petites modifications fonctionnent avec Python 3.


9 commentaires

Quelques remarques: 1. Le paramètre de forme sur le constructeur ndarray peut simplement être un entier au lieu d'un tuple. 2. dtype = flotteur est la valeur par défaut. 3. Dans Python 3, vous pouvez omettre les arguments sur Super () dans ce cas. Combinant ces remarques, les deux premières lignes du constructeur réduisent vers super () .__ init __ (taille) .


Oh, et je remarque juste que votre appel Super () est incorrect - devrait être super (tableau, auto) dans Python 2.x.


Tu as raison, j'ai édité ma réponse. (La signature du constructeur est sans papiers, comme d'habitude.)


@Philipp: Il est documenté dans la doctrine de la classe, pas du constructeur lui-même. Mais c'est en fait où le Doc appartient.


@Sven: Ce que je veux dire, c'est que le doc) dit forme doit être un tuple, et ne dit pas DTYPE par défaut sur float .


@Philipp: Mon docstring fait me donne la valeur par défaut pour dtype . (Peut-être une version différente?) Et une forme peut Toujours être un tuple ou un entier, mais le DOC dit en effet "tuple d'INTS" dans ce cas.


@Sven: En effet, j'ai manqué le dtype = float Déclaration. En ce qui concerne forme , j'ai été perplexe car le dernier exemple utilise un tuple d'un élément au lieu d'un entier.


@Philipp: Cela ne fonctionnera pas, car il n'y a pas de __ init __ méthode dans ndarray . Je sais que dans Python 3, il tente d'appeler objet .__ init __ (et échoue en raison du mauvais nombre de paramètres). Merci pour les commentaires sur le Zeros Cependant, cela vous aide à comprendre d'où cela vient.


@max: C'est fait du travail , je l'ai testé, pas besoin de bowervote! L'appel au constructeur ndarray non existant est faux et je l'ai supprimé. La matrice est correctement initialisée par la méthode __ nouvelle __ .



6
votes

Si vous n'aimez pas NDARARRAY code> interface, ne l'héritez pas. Vous pouvez définir votre propre interface et déléguer le reste à NDARRAY et NUMPY.

import functools
import numpy as np


class Array(object):

    def __init__(self, size):
        self._array = np.zeros(size)

    def __getattr__(self, attr):
        try: return getattr(self._array, attr)
        except AttributeError:
            # extend interface to all functions from numpy
            f = getattr(np, attr, None)
            if hasattr(f, '__call__'):
                return functools.partial(f, self._array)
            else:
                raise AttributeError(attr)

    def allzero(self):
        return np.allclose(self._array, 0)


a = Array(10)
# ndarray doesn't have 'sometrue()' that is the same as 'any()' that it has.
assert a.sometrue() == a.any() == False
assert a.allzero()

try: a.non_existent
except AttributeError:
    pass
else:
    assert 0


6 commentaires

Très propre. Je suppose que tous les fonctions globales numpy ont la même sémantique lorsqu'ils sont appelés avec ndarray comme la méthode d'instance de même nom de ndarray .


Pour passer à Python 3, je viens de supprimer (objet) de la définition de la classe, correct? [Ne pas laisser cela causerait des problèmes.]


@max: Le code fonctionne sans changement sur 2.x et Python 3.


Il me semble manquer quelque chose ici. Vous ne dérivez pas de ndarray , mais si un attribut est demandé, vous essayez d'abord d'obtenir l'attribut à partir de l'instance ndarray . Ne serait-il pas beaucoup plus facile de tirer de ndarray en premier lieu? Vous pouvez toujours ajouter la magie pour ajouter les fonctions de niveau de module en numpopie en tant que méthodes, mais je ne pense pas que ce soit une bonne idée non plus, car la plupart d'entre eux sont déjà des méthodes, et le reste ne avoir un sens comme une méthode (à très peu d'exceptions près).


@Sven Marnach: Le principe est que l'OP trouve ndarray ennuyeux à utiliser. La délégation est une approche plus flexible pour changer l'interface de classe que l'héritage. Le code n'est pas une solution finale, mais il ne s'agit que d'un simple exemple de squelette qui permet de l'étendre pour utiliser les approches de la liste de noirs, de liste blanche, etc. Je suis d'accord sur les fonctions de niveau de module. Le code montre comment vous pouvez le faire; Cela ne préconise pas que c'est une chose sensible à faire.


@ J.f.sebastian: Merci pour la clarification - je suis tout à fait d'accord.



4
votes

L'héritage de Ndarray est un peu délicat. ndarray n'a même pas la méthode __ init (auto,) ___ , donc il ne peut donc pas être appelé de la sous-classe, mais il y a des raisons à cela. Veuillez consulter la documentation numpy de sous-classement .

Au fait, pourriez-vous être plus spécifique de vos besoins particuliers? Il est toujours assez facile de cuisiner une classe (utilisation de Ndarray) pour vos propres besoins, mais une sous-classe de Ndarray pour réussir toutes les machines numériques est un problème assez différent.

Il semble que je ne peux pas commenter mon poteau, impair
@Philipp: On s'appellera par Python, mais pas par NUMPY. Il existe trois façons d'instancier Ndarray et des directives sur la manière de gérer tous les cas sont donnés sur ce document.


3 commentaires

Il me semble que ce document manquait. Mais pourquoi la méthode __ init __ dans mon exemple est appelée même si ndarray avait __ nouveau __ ?


@Philipp: Voyez mon commentaire à votre réponse.


Je voulais juste ma propre classe que je contrôlais pleinement comment elle est instanciée. Vous avez raison de sous-classement Ndarray est trop difficile. Je suivrai l'approche du conteneur dans @ j.f. Sébastien.