Kirjoittaja Aihe: Python viittaus perityn luokan jäseneen  (Luettu 3081 kertaa)

ilkant

  • Käyttäjä
  • Viestejä: 1299
  • Kubuntu
    • Profiili
Python viittaus perityn luokan jäseneen
« : 05.01.24 - klo:02.15 »
Kokeilin FaceBookin esimerkkiohjelmaa

Koodia: [Valitse]
class Sport:
    def __init__(self, name):
        self.name = name

class Football(Sport):
    def __init__(self, teams):
        self.teams = teams

    def match(self):
        return f"{self.name} match: {self.teams[0]} vs {self.teams[1]}"

print(Football(["Team A", "Team B"]).match())

Koneessa on Kubuntu 23.10 ja python versio 3.11.6.

Eikö tuon pitäisi toimia? Tarkoittaa, että luokka Football perii luokan Sport attribuutin name ja sitä voi käyttää luokassa Football. Antaa kuitenkin virheilmoituksen:

Koodia: [Valitse]
AttributeError: 'Football' object has no attribute 'name'

Onko kysymys pythonin version bugista? Vai onko pythonissa joku erityinen tapa viitata perittyyn luokkaan? Pieni googlaus ei tuonut vastausta.

Tomin

  • Palvelimen ylläpitäjä
  • Käyttäjä / moderaattori+
  • Viestejä: 11478
    • Profiili
    • Tomin kotisivut
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #1 : 05.01.24 - klo:08.29 »
Lisää konstruktoriin (__init__) kutsu yläluokan konstruktoriin. Esimerkiksi:
Koodia: [Valitse]
    def __init__(self, name, teams):
        super().__init__(name)
        self.teams = teams
Automaattinen allekirjoitus:
Lisäisitkö [RATKAISTU] ketjun ensimmäisen viestin aiheeseen ongelman ratkettua, kiitos.

SuperOscar

  • Käyttäjä
  • Viestejä: 4016
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #2 : 05.01.24 - klo:16.43 »
Tuohon voisi vielä jatkaa, että jos Sport.name on ajateltu lajin nimeksi, ehkä johdannaisluokan pitäisi asettaa se:

Koodia: [Valitse]
class Football(Sport):
    def __init__(self, teams):
        super().__init__('Football')
        # …
pöytäkone 1, NUC: openSUSE Leap 15.6, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; RPi 1: FreeBSD 14-RELEASE; RPi 2: LibreELEC 11

ilkant

  • Käyttäjä
  • Viestejä: 1299
  • Kubuntu
    • Profiili
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #3 : 06.01.24 - klo:03.16 »
Kiitokset vastauksista!

Sitä jään ihmettelemään kun siellä FaceBook-ryhmässä oli sitten monivalintana vaihtoehtoja, mitä ohjelma tulostaa. Ja monet vastasivat siihen yhdellä vaihtoehdolla. Mielestäni tässä voi ajatella, että some muokkaa ajatusmaailmaa niin, että se muuttuu virtuaaliseksi. Ja siis nyt ei edes tulla ajatelleeksi, että ohjelma ei toimi edes. Noitten vastausten takia epäilin, että python-kääntäjässä on bugi. Nimittäin tarkistin, että en ole tehnyt mitään kirjoitusvirhettä kirjoittaessani valokuvasta koodit tekstieditorilla.

Oma taustani on Java-maailmasta. Olen omin päin sitten opetellut Pythonia. Ja kommelluksin. Esimerkiksi silloin opettelun alussa tein luokan ja konstruktorin. Vahingossa olin katsonut, että initissä pitää olla kolme alaviivaa. No kun kysyin FaceBookissa, miksei ohjelma toimi, niin osa nauroi. Kukaan ei vastannut sitä oikeaa syytä. Se selvisi sitten sattumalta. Ja luokan attribuuttien olemassaolo (eksistenssi) oli uutta, jolla Pythonilla voi kikkailla kun Javalla ei sellaisia voi tehdä. Esim. ettei luokassa tarvitse määritellä attribuutteja vaan niitä voi lisätä ajon aikana. Toivottavasti olen ymmärtänyt oikein.

Pythonilla aloin tehdä yhtä (minulle) kohtalaisen laajaa ohjelmaa. Aluksi hämmästelin, miten ilmaisuvoimainen Python on. Paljon vähemmällä koodilla tekee paljon. Esimerkiksi funktioiden parametrin välityksessä ei tarvita niin tiukkaa tyypitystä kuin Javassa. Ja paljon muuta.

Ja tuossa esitetyssä ohjelmapätkässä kuvittelin, että tuo super tapahtuu automaattisesti ilman erillistä ohjeistusta. Kuten monet muut toiminnot esim. listojen käsittelyssä yms.
« Viimeksi muokattu: 06.01.24 - klo:03.21 kirjoittanut ilkant »

SuperOscar

  • Käyttäjä
  • Viestejä: 4016
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #4 : 06.01.24 - klo:16.41 »
Ja siis nyt ei edes tulla ajatelleeksi, että ohjelma ei toimi edes. Noitten vastausten takia epäilin, että python-kääntäjässä on bugi. Nimittäin tarkistin, että en ole tehnyt mitään kirjoitusvirhettä kirjoittaessani valokuvasta koodit tekstieditorilla.

Yksi mahdollisuus on, että koodi on Python 2:sta, mutta Python 3 käyttäytyy eri lailla. En pääse tarkistamaan, koska Python 2:ta ei enää koneella ole.

Lainaus
Ja tuossa esitetyssä ohjelmapätkässä kuvittelin, että tuo super tapahtuu automaattisesti ilman erillistä ohjeistusta.

En muista yksityiskohtia, mutta kokeilemallakin selviää, että metodit periytyvät ilman super().__init__()-kutsuakin.

Vinkiksi voisin antaa dir()-funktion, jolla näkee kivasti aina olion nimiavaruuden mm. metodit ja instanssimuuttujat. Kokeile esimerkiksi:

Koodia: [Valitse]
f = Football(['Team A', 'Team B'])
dir(f)

pöytäkone 1, NUC: openSUSE Leap 15.6, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; RPi 1: FreeBSD 14-RELEASE; RPi 2: LibreELEC 11

Tomin

  • Palvelimen ylläpitäjä
  • Käyttäjä / moderaattori+
  • Viestejä: 11478
    • Profiili
    • Tomin kotisivut
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #5 : 06.01.24 - klo:19.36 »
Ja siis nyt ei edes tulla ajatelleeksi, että ohjelma ei toimi edes. Noitten vastausten takia epäilin, että python-kääntäjässä on bugi. Nimittäin tarkistin, että en ole tehnyt mitään kirjoitusvirhettä kirjoittaessani valokuvasta koodit tekstieditorilla.

Yksi mahdollisuus on, että koodi on Python 2:sta, mutta Python 3 käyttäytyy eri lailla. En pääse tarkistamaan, koska Python 2:ta ei enää koneella ole.

Konstruktoria ei kutsuta automaattisesti edes Python 2:ssa. Syntaksin tosin pitää yleensä olla vähän eri:

Koodia: [Valitse]
super(Sport, self).__init__('Football')
Lisää selitystä:
Python 3:n dokumentaatio: https://docs.python.org/3/library/functions.html?highlight=super#super
Python 2:n dokumentaatio: https://docs.python.org/2/library/functions.html?highlight=super#super

Pythonissa yläluokan metodeja ei yleensäkään kutsuta implisiittisesti (automaattisesti) vaan ne pitää aina kirjoittaa auki vaikkapa tuon superin avulla. Tämä pätee myös konstruktoreihin. Muutenkin Pythonissa asioita pitää tehdä yleensä eksplisiittisesti. Esimerkiksi ei ole C++:n tyylistä this-muuttujaa vaan self määritellään aina metodin argumenteissa.
Automaattinen allekirjoitus:
Lisäisitkö [RATKAISTU] ketjun ensimmäisen viestin aiheeseen ongelman ratkettua, kiitos.

SuperOscar

  • Käyttäjä
  • Viestejä: 4016
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #6 : 06.01.24 - klo:21.13 »
Pythonissa yläluokan metodeja ei yleensäkään kutsuta implisiittisesti

Tätä kuitenkin hämärtää se, että metodit itsessään siirtyvät ”implisiittisesti”. Ajatus on varmaan jollain lailla ymmärrettävä, muttei välttämättä avaudu aloittelijalle.
pöytäkone 1, NUC: openSUSE Leap 15.6, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; RPi 1: FreeBSD 14-RELEASE; RPi 2: LibreELEC 11

Tomin

  • Palvelimen ylläpitäjä
  • Käyttäjä / moderaattori+
  • Viestejä: 11478
    • Profiili
    • Tomin kotisivut
Vs: Python viittaus perityn luokan jäseneen
« Vastaus #7 : 07.01.24 - klo:13.54 »
Itse ainakin ajattelen niin päin, että olion attribuutit pitää asettaa jossakin metodissa ja jos koodia ei ole ajettu, niin ko. attributtia ei ole myöskään voitu asettaa. Saman luokan ilmentymällä voi olla jopa aivan eri attribuutit kuin toisella:

Koodia: [Valitse]
class Olio:
    def __init__(self, a):
        if a == 1:
            self.foo = True
        else:
            self.bar = True

eka = Olio(1)
toka = Olio(2)

assert hasattr(eka, "foo")
assert not hasattr(eka, "bar")
assert not hasattr(toka, "foo")
assert hasattr(toka, "bar")
(assertit voi vaihtaa printteihin, jos haluaa nähdä tuloksen, tai käyttää dir() funktiota kuten aiemmin neuvottiin)

Metodeista ajattelen, että ne periytyvät, kun määritellään class Alaluokka(Yläluokka).
Automaattinen allekirjoitus:
Lisäisitkö [RATKAISTU] ketjun ensimmäisen viestin aiheeseen ongelman ratkettua, kiitos.