Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  5 1862
Jeg forsøker å implementere en egen klasse som inneholder en numpy array med litt ekstra. Denne skal oppføre seg som om man behandlet arrayet den inneholder direkte, men ha noe ekstra funksjonalitet. Av forskjellige grunner virker ikke det å arve ndarray som en god løsning.

I utgangspunktet fungerer dette fint, med unntak av en ting. For jeg skulle gjerne kunne bruke dette objektet som argument til numpy.empty_like(), slik at det nye arrayet ble av samme størrelse og datatype som arrayet i min egen klasse.

Her er et minimalistisk eksempel:

Kode

class My_class:
    def __init__(self, size):
        self.my_array = numpy.zeros(size, dtype=numpy.int)
        
    def __getitem__(self, val):
        return self.my_array[val]
Den faktiske implementasjonen inneholder noen ekstra funksjoner og ekstra data som gjør arv mindre egnet, men det viser poenget. Jeg kan instansiere og bruke denne på samme måte som arrayet direkte. Men dersom jeg forsøker med følgende:

Kode

my_obj = My_class((10,10))
new_array = numpy.empty_like(my_obj)
... ender, ikke overraskende, new_array opp som et nulldimensjonalt array med datatype object. Jeg har prøvd å definere både "__len__(self)" og variabelen "shape", slik at både len() og numpy sin shape-funksjon fungerer, men resultatet er det samme. Et alternativ er å skrive "empty_like(my_obj.my_array)", men det vil være lite elegant.

Er det noen interne funksjoner eller variabler som kan defineres slik at størrelse og datatype blir korrekt når man bruker denne som utgangspunkt til empty_like, zeros_like osv? Eller er det rett og slett umulig?
Vet du ikke ønsket arv, men tror nok det er den enkleste løsningen her. Funksjonene er ikke så godt dokumenterte, så ikke så enkelt å finne ut av hva de forventer for å klare å vite størrelsen på de nye objektene. Men om du arver fra numpy.ndarray så ser det ut som du får funksjonaliteten du ønsker.

Ser du nevner at grunnet implementasjoner så er ikke det ønskelig. Men i så fall prøver objektet ditt å være 2 ting på en gang. Har du eksempler på årsaker til at arv ikke vil funke for deg i dette tilfelle?
Sist endret av etse; 25. mai 2015 kl. 15:08.
Skjønner ikke hvorfor du ikke bruker arv, men:

Kode

class My_class:
    def __init__(self, size):
        self.__array__ = lambda : numpy.zeros(size, dtype=numpy.int)

    def __getitem__(self, val):
        return self.__array__()[val]

my_obj = My_class((10,10))
new_array = numpy.empty_like(my_obj)

Kode

>>> print new_array.shape
(10, 10)
Løsningen til DumDiDum løser problemet uten arv, men har problemet med at den lager et nytt tomt array hver gang noen kaller __array__ (noe mange ulike ting i numpy gjør). Dette er trolig ikke ønskelig.

En litt mer riktig løsning blir da:

Kode

import numpy

class MyClass:
    def __init__(self, size):
        self.my_array = numpy.zeros(size, dtype=numpy.int)

    def __getitem__(self, val):
        return self.my_array[val]

    def __array__(self):
        return self.my_array

my_obj = MyClass((10, 10))
new_array = numpy.empty_like(my_obj)

print(new_array)
og fordi PEP8: Klassenavn skal ha camelcase
Sist endret av etse; 25. mai 2015 kl. 15:24.
Sorry, det var slurvete av meg. Testen .__array__ funksjonaliteten live i interpreteren og skreiv koden rett inn i innlegget.
Etter litt sortering av kode og tanker, kom jeg frem til at arv er en grei løsning likevel. Takk for hjelpen til begge uansett, det hjalp på forståelsen.

Sitat av etse Vis innlegg
og fordi PEP8: Klassenavn skal ha camelcase
Vis hele sitatet...
Camelcase er djevelens kodestil. Selv om PEP8. Men jeg skal prøve å vende meg til tanken.