Vadovėlis/Įvadas į objektinį programavimą Python 3

Iš Pitonas.

Objektinis programavimas

Iki šiol rašei kodą pagal procedūrinio programavimo taisykles. Tačiau, yra daug programų, kurios parašytos pagal objektinio programavimo taisykles. Žinoti abu programavimo tipus ir jų skirtumus yra labai svarbu. Informatikoje, daug svarbių kalbų, tokių kaip C++ ar Java, dažnai naudoja objektinio programavimo taisykles.

Pradedantiesiems ir mokiniams, neturintiems programavimo žinių, objektinis programavimas dažnai gali atrodyti painus ir tai yra visiškai normalu. Nesijausk blogai, jei nesiseka suprasti iš pat pradžių. Jei šis skyrius nepadės tau suprasti, yra ir daugiau informatyvių šaltinių, kurie padės atsakyti į visus klausimus.

Šis skyrius yra padalintas į keletą pamokų. Kiekviena pamoka - skirta paaiškinti skirtingas objektinio programavimo dalis. LABAI SVARBU suprasti jas visas. Nepamiršk prieš kiekvieną pamoką perskaityti įžangą, kuri paaiškins pagrindines idėjas, sąvokas ir kitas objektinio programavimo sritis.

Įžanga

Tu jau žinai, kad funkcija turi konkrečią paskyrtį ir ji gali būti įvairi: rinkti įvestis, atlikti matematinius skaičiavimus, atvaizduoti ar kitaip manipuliuoti duomenimis. Paprastai, funkcijos manipuliuoja duomenimis, kurie yra aprašyti atskirai. Šie duomenys yra dažnai perduodami iš vienos funkcijos į kitą. Ir, kai programa pasidaro per didelė, tai padaro duomenų perdavimą komplikuotą. Pavyzdžiui, parašei programą, kuri kintamuosiuose išsaugo produkto duomenis. Kai klientas paprašo informacijos apie produktą, reikia išrinkti visus kintamuosius, saugančius tuos duomenis ir pateikti atitinkamoms funkcijoms. Laikui bėgant ir saugant vis daugiau duomenų apie turimus produktus, tu sugalvoji išsaugoti turimą informaciją sąrašuose ar žodynuose. Norint, jog tavo programa veiktų, tu dabar turi redaguoti kiekvieną funkciją, kuri naudojo tuos kintamuosius, taip, kad dabar ji galėtų priimti ir manipuliuoti sąrašus ar žodynus. Įsivaizduok kiek laiko tau reikėtų norint peržiūrėti ir pakeisti šimtus failų. Tu išprotėtum! Nekalbant apie tai, jog klaidas daro net ir labiausiai patyrę programuotojai, tad taip pat reikėtų taisyti begalę klaidų. Toks programavimas yra pernelyg neoptimalus. Procedūrinis programavimas yra paremtas funkcijomis (procedūromis). Objektinis programavimas yra paremtas objektais. Ar prisimeni, kaip procedūrinė programa atskyrė duomenis nuo kodo? Ar prisimeni programą, kuri turėjo šimtus failų ir norint kažką pakeisti reikėdavo ilgai joje narpstytis? Galvok apie objektą kaip apie minėtų failų ir duomenų „kombinaciją“ į vieną esybę. Technine prasme, objektas yra esybė, kuri savyje turi duomenis ir veiksmus su tais duomenimis (kodą, funkcijas, t.t.).

Duomenis objekto viduje vadiname atributais.

Funkcijas objekto viduje vadiname metodais.

Galvok apie duomenų atributus kaip apie kintamuosius.

Galvok apie metodus kaip apie funkcijas.

Pažiūrėk į paprastą, kasdienį pavyzdį. Lemputė ir jungiklis tavo kambaryje. Atributai bus štai tokie.

  • šviesa_įjungta (True False)
  • jungiklio_pozicija (Viršuje arba Apačioje)
  • elektros_tekėjimas (True arba False)

Metodai būtų štai tokie.

  • pakeisti_jungiklio_poziciją
  • pakeisti_elektros_tekėjimą

Atributai gali būti matomi ir nematomi. Pavyzdžiui, tu negali matyti elektros tekančios į lemputę. Tu tik žinai, kad elektra išties teka, nes ji tuo metu skleidžia šviesą. Nepaisant to, tu gali matyti jungiklio poziciją (jungiklio_pozicija) ir taip pat tu matai ar šviesa yra įjungta ar ne (šviesa_įjungta). Kai kurie metodai yra privatūs. Tai reiškia, jog jų reikšmės neišeina tiesiogiai pakeisti. Pavyzdžiui, tu negalėtum pakeisti elektros tėkmės tiesiogiai, nebent būtų nukerpami laidai (to nedaryk ir dėl šio pavyzdžio; manyk, jog laidai neegzistuoja). Tu taip pat negali tiesiogiai įtakoti lemputės šviesos (ne, tu negali atsukti lemputės ar jos sudaužyti!). Bet tu visada gali šiuos atributus įtakoti netiesiogiai naudojant objekto metodus. Jeigu nesumokėsi mokesčių, metodas pavadinimu pakeisti_elektros_tekėjimą pakeis elektros_tekėjimas reikšmę į False. Jei tu įjungsi jungiklį, pakeisti_jungiklio_poziciją metodas pakeis šviesa_įjungta atributo reikšmę.

Dabar jau tikriausiai galvoji, „Ką tai turi bendro su Python'u?“ ar, „Aš nesuprantu, bet kaip man sukurti tą objektą?“. Na, beveik priėjai prie atsakymų! Tik turiu paaiškinti dar vieną dalyką prieš neriant į kodą.

Python'e objekto atributai ir metodai yra nurodomi klasės. Galvok apie klasę kaip apie objekto techninį piešinį. Pavyzdžiui, tavo namai - objektas kuriame gyveni - taip pat jį gali vadinti butu, vasarnamiu, prakartėle ar bet kuo kitu, buvo pastatytas naudojant techinius piešinius. Šie techniniai piešiniai būtų vadinami klasėmis, kurios buvo panaudotos projektuojant tavo namus, butą, vasarnamį, na, supranti apie ką kalbu.

Dar kartą, klasė pasako, kaip sukurti objektą. Techniniais terminais tariant, ir tai yra labai svarbu, klasė nusako naudojamus duomenų atributus ir metodus objekte.

Norint sukurti klasę, mes suprogramuojame klasės apibrėžimą. Klasės apibrėžimas, tai grupė komandų, kurios nusako objekto atributus ir metodus.

Pirma pamoka

Apačioje yra procedūrinė programa, kuri atlieka paprastą matematinį veiksmą su vartotojo įvestu skaičiumi.


# Programa parašyta Mitchell Aikens
# Nėra autoriaus teisių
# 2012

# Procedūra 1
def main():
    try:
        # Pasiimk skaičių, kurį manipuliuosi.
        sk = float(input("Įrašyk skaičių.\n"))
        # Išsaugok naują skaičių į kintamąjį. Prieš tai, su pasiimtu skaičiumi atlik matematinius
        # veiksmus naudojant procedūrą 2
        pridėksk = pridėkpenkis(sk)
        # Išsaugok naują skaičių į kintamąjį. Prieš tai, su ankščiau išsaugotu skaičiu atlik
        # matematinius veiksmus naudojant procedūrą 3
        dauginksk = daugink(pridėksk)
        # Paduok skaičių procedūrai 4
        rodyk(dauginksk)
    # Susidorok su išimtimis, kurios gali atsirasti dėl netinkamo vartotojo skaičiaus įvedimo
    except ValueError:
        print("Privalai įvesti tinkamą skaičių.\n")
        # Atstatyk kintamojo num reikšmę, kad ištrintum netinkamą vartotojo įvestį.
        sk = 0
        # Dar kartą iškviesk main.
        main()

# Procedūra 2
def pridėkpenkis(sk):
    return sk + 5

# Procedūra 3
def daugink(pridėksk):
    return pridėksk * 2.452

# Procedūra 4
def rodyk(dauginksk):
    # Parodyk galutinį rezultatą.
    print("Galutinis rezultatas yra", dauginksk)

# Kviesk procedūrą 1
main()

Jei įrašysi skaitemnį "5", gausi išvestį parodytą žemiau.

Įrašyk skaičių.
5
Galutinis rezultatas yra 24.52

Jei įrašysi reikšmę "g", tada pasitaisysi ir įrašysi skaitmenį "8", tada gausi išvestį parodytą žemiau.

Įrašyk skaičių.
g
Privalai įvesti tinkamą skaičių.

Įrašyk skaičių.
8
Galutinis rezultatas yra 31.875999999999998

Žemiau matai klasę ir programą, kuri naudoja nurodytą klasę. Ši objektinio programavimo būdu parašyta programa daro tą patį, ką prieš tai darė procedūriniu programavimo būdu parašyta programa. Apžiūrėk keletą svarbių objektinio programavimo būdo konceptų prieš neriant į ankščiau minėtą klasę ir programą. Norint sukurti klasę, naudok class raktažodį. Po raktažodžio rašyk pavadinimą, kurį norėtum, jog turėtų klasė. Dažnai naudojama praktika kuriant klasių pavadinimus yra NaujųŽodžiųRašymasIšDidžiosiosRaidės. Jei norėčiau sukurti klasę pavadinimu purvinoskojinės, kodas atrodytų taip:

class PurvinosKojinės

Iš pradžių pažiūrėk į klasę. Programa, kuri naudos šią klasę, bus parodyta vėliau.

# Failo pavadinimas: ooppavyzdys.py
# Programa parašyta Mitchell Aikens
# Nėra autoriaus teisių
# 2012
# OOP Demonstracija - Klasė

class SkKeitimas:

    def __init__(self):
        self.__skaičius = 0

    def pridėkpenkis(self, sk):
        self.__skaičius = sk
        return self.__skaičius + 5

    def padaugink(self, pridėtas):
        self.__pridėtas = pridėtas
        return self.__pridėtas * 2.452

Programa, kuri naudoja viršuje esančią klasę yra parašyta žemiau.

# Failo pavadinimas: ooppavyzdys.py
# Mitchell Aikens
# Nėra autoriaus teisių
# 2012
# OOP Demonstracija - Programa

import ooppavyzdys

matkė = ooppavyzdys.SkKeitimas()

def main():

    sk = float(input("Įrašyk skaičių.\n"))

    pridėtas = matkė.pridėkpenkis(sk)

    daugintas = matkė.padaugink(pridėtas)

    print("Galutinis rezultatas yra", daugintas)

main()

Tikriausiai dabar esi pasimetęs. Tai visiškai suprantama. Iš pradžių, pasistenk suprasti klasę. Klasė yra pavadinta "SkKeitimas" Ši klasė turi tris metodus

  • __init__
  • pridėkpenkis
  • padaugink

Šie trys metodai savyje turi labai panašų kodą.

def __init__(self):
    self.__skaičius = 0

def pridėkpenkis(self, sk):
    self.__skaičius = sk
    return self.__skaičius + 5

def padaugink(self, pridėtas):
    self.__pridėtas = pridėtas
    return self.__pridėtas * 2.452

Atkreipk dėmesį į tai, jog kiekvienas metodas turi parametrą pavadinimu „self“. Kiekvienas klasės metodas turi būtinai turėti šį parametrą. Šis parametras nebūtinai turi būti su pavadinimu „self“, bet tai laikoma gerąja praktika, tad tikriausiai ir tu turėtum jį taip vadinti. Šis parametras yra reikalingas kiekviename metode nes, kai jis yra iškviečiamas, jis turi žinoti, su kuriuo objekto atributu turėtų atlikti operacijas. Net kai turi tik vieną objektą, turi pasirūpinti, kad programa žinotų, jog nori naudoti atributus aprašytus būtent toje klasėje. Todėl turi būti saugus ir naudoti „self“ parametrą.

Peržiūrėk pirmą metodą.

def __init__(self):

Dauguma Python'o klasių turi __init__ metodą, kuris yra paleidžiamas automatiškai kiekvieną kartą, kai atmintyje yra sukuriamas tos klasės objektas (kai vykdoma programa kreipiasi į klasę, yra sukuriama tos klasės objektas). Šis metodas yra paprastai vadinamas inicijavimo metodu. Kai šis metodas yra paleidžiamas, „self“ parametras yra automatiškai priskiriamas sukurtam objektui. __init__ metodas inicijuoja klasės atributus, dėl šios priežasties jis yra pavadintas inicijavimo metodu. Vykdant __init__ metodą, skaičius atributui priskiriame 0. Į objekto atributą skaičius kreipiamės panaudojant tašką.

def __init__(self):
    self.__skaičius = 0

Kodas self.__skaičius = 0 reiškia, jog objekte esančio „skaičius“ atributo reikšmė tampa lygi 0.

Pažiūrėk į kitą metodą.

def pridėkpenkis(self, sk):
    self.__skaičius = sk
    return self.__skaičius + 5

Šis metodas yra pavadintas „pridėkpenkis“. Jis priima parametrą pavadinimu „sk“. Metode esanti komanda priskiria „sk“ reikšmę objekte esančiui atributui pavadinimu „skaičius“. Tada metodas prideda 5 prie „skaičius“ ir jį grąžina į tą vietą, kur metodas buvo iškviestas.

Pažiūrėk į trečiajį metodą.

def padaugink(self, pridėtas):
    self.__pridėtas = pridėtas
    return self.__pridėtas * 2.453

Šis metodas yra pavadintas „padaugink“. Jis priima parametrą pavadinimu „pridėtas“. Metodas priskiria priimtą reikšmę objekte esančiam atributui su pavadinimu „pridėtas“ ir grąžina „pridėtas“ atributo ir 2.452 sandaugą į tą vietą, kur metodas buvo iškviestas.

Ar atkreipei dėmesį į tai, jog kiekvieno metodo viduje „self“ atributas prasideda su dviem pabraukimais? Pabandyk suprasti kodėl. Prieš tai buvo minėta, jog objektas, metodų pagalba, dirba su atributais apibrėžtais jame pačiame. Būtų idealu, jei tuos atributus galėtum pakeisti TIK SU METODAIS ESANČIAIS TAME OBJEKTE. Įmanoma turėti iššorinį kodą, kuris galėtų manipuliuoti tais pačiais atributais. Norint „paslėpti“ atributus, taip, kad juos matytų tik metodai aprašyti pačiame objekte, turi naudoti du pabraukimus prieš objekto pavadinimą, taip kaip ir buvo padaryta. Ištrynus abu pabraukimus nuo atributo pavadinimo tu juo galėsi manipuliuoti kodu, kuris parašytas objekto išorėje.

Pažiūrėk į programą, kuri naudoja aptartą klasę.

Atkreipk dėmesį į pirmą eilutę, kuri nėra komentaras.

import ooppavyzdys

Ši kodo eilutė importuoją klasę, kurią išsaugojai atskirame faile (modulyje). Klasės nebūtinai turi būti talpinamos atskiruose failuose, bet tai yra priimta kaip geroji praktika, tad yra verta jau nuo pat pradžių priprasti prie modulių importavimo.

Kita eilutė:

matkė = ooppavyzdys.SkKeitimas()

Ši eilutė sukuria SkKeitimas pavadinimu „ooppavyzdys“ modulyje patalpintos klasės objektą, kuris yra priskiriamas „matkė“ kintamajam. Sintaksė atrodo taip: moduliopavadinimas.Klasėspavadinimas(). Toliau apibrėžiama main funkcija ir paimamas skaičius iš vartotojo priskiriamas kintamajam sk.

Kita eilutė pridėtas = matkė.pridėkpenkis(sk) nusiunčia „sk“ kintamojo reikšmę metodui pavadinimu „pridėkpenkis“. Metodas yra aprašytas klasėje, kurios objektą sukūrei kintamajame pavadinimu „matkė“. „pridėkpenkis“ metodas grąžina apskaičiuotį reikšmę, kuri priskiriama kintamajam pavadinimu „pridėtas“.

Kita eilutė daugintas = matkė.daugink(pridėtas) nusiunčia „pridėtas“ kintamojo reikšmę metodui pavadinimu „daugink“. Metodas yra aprašytas objekto „matkė“ klasėje. „daugink“ metodas apskaičiuja ir grąžina reikšmę, kuri yra priskiriama kintamajam pavadinimu „daugintas“.

Paskutinė main() funkcijos eilutė atspausdina „Galutinis rezultatas yra <kintamojo daugintas reikšmė>“.

Programos paskutinė eilutė iškviečia main funkciją, kuri įvykdo žingsnius nurodytus viršuje.