Ubuntu Suomen keskustelualueet
Ubuntun käyttö => Ohjelmointi, palvelimet ja muu edistyneempi käyttö => Aiheen aloitti: ilkant - 05.01.24 - klo:02.15
-
Kokeilin FaceBookin esimerkkiohjelmaa
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:
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.
-
Lisää konstruktoriin (__init__) kutsu yläluokan konstruktoriin. Esimerkiksi:
def __init__(self, name, teams):
super().__init__(name)
self.teams = teams
-
Tuohon voisi vielä jatkaa, että jos Sport.name on ajateltu lajin nimeksi, ehkä johdannaisluokan pitäisi asettaa se:
class Football(Sport):
def __init__(self, teams):
super().__init__('Football')
# …
-
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.
-
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.
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:
f = Football(['Team A', 'Team B'])
dir(f)
-
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:
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.
-
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.
-
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:
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).