Kuinka ei enää pelätä Pythonia

Sukella kieli-ohjeisiin

Lähde

Ensimmäisen tai kahden vuoden ajan, kun aloitin koodauksen, ajattelin, että kielen oppimisessa on kyse syntaksin oppimisesta. Joten se on kaikki mitä tein.

Sanomattakin on selvää, että minusta ei tullut suurta kehittäjää. Olin jumissa. Sitten, yksi hieno päivä, se vain napsautti. Tajusin, että tein tämän väärin. Syntaksin oppimisen tulisi olla vähiten huolta. Tärkeää on kaikki muu kielen suhteen. Mikä tarkalleen on? Jatka lukemista.

Tämä artikkeli on jaettu kolmeen pääosaan: tietomalli, suoritusmalli ja Lexical-analyysi.

Tämä artikkeli on enemmän tietoa asioiden toiminnasta Pythonlandissa - päinvastoin kuin Pythonin oppiminen. Löydät verkossa monia oppimislähteitä.

Se, mitä en löytänyt verkosta, oli Pythonin ainoa yleinen 'getchas' -lähde. Lähde, joka selittää kielen toiminnan. Tämä yrittää ratkaista ongelman. Luulen, että olen tullut lyhyeksi, siinä on niin paljon!

Kaikki täältä tulee virallisista asiakirjoista. Olen tiivistänyt sen - tärkeisiin kohtiin, järjestänyt tavaraa ja lisännyt esimerkkejäni. Kaikki linkit osoittavat dokumentaatioon.

Ilman tarvetta, mennään eteenpäin.

Datamalli

Kohteet, arvot ja tyypit

Objektit ovat Pythonin tietojen abstraktiota.

Jokaisella esineellä on ainutlaatuinen kiinteä identiteetti, kiinteä tyyppi ja arvo.

'Kiinteä' tarkoittaa objektin identiteettiä ja tyyppiä ei voi koskaan muuttua.

Arvo voi muuttua. Objekteja, joiden arvo voi muuttua, kutsutaan muuttuviksi, kun taas objekteja, joiden arvo ei voi muuttua, kutsutaan muuttumattomiksi.

Vaihdettavuus määritetään tyypin mukaan:

  • Numerot, merkkijonot ja Tuples ovat muuttumattomia
  • Listat ja sanakirjat ovat muutettavissa

Objektien identiteettiä voidaan verrata operaattorin avulla.

id () palauttaa identiteetin

type () palauttaa tyypin

Huomaa: Muuttamattoman säilöobjektin arvo, joka sisältää viittauksen muuttuvaan objektiin, voi muuttua, kun viimeksi mainitun arvo muuttuu. Säiliötä pidetään kuitenkin edelleen muuttumattomana, koska sen sisältämää esinekokoelmaa ei voida muuttaa. Joten muuttumattomuus ei ole ehdottomasti sama kuin jolla on muuttumaton arvo.

Tämä huomautus sai pään pyörittämään kaksi ensimmäistä kertaa lukeessani sitä.

Yksinkertainen käännös: Muutettavuus ei ole sama kuin muuttuva arvo. Seuraavassa esimerkissä tuple on muuttumaton, kun taas sen arvo muuttuu jatkuvasti (luettelon muuttuessa).

Esimerkki:

>>> t = ("a", [1]) # kokonaisuus merkkijonoa ja luetteloa
>>> tunnus (t)
4372661064
>>> t
('a', [1])
>>> tyyppi (t)

>>> t [1]
[1]
>>> t [1] .apu (2)
>>> t
('a', [1, 2])
>>> tunnus (t)
4372661064
>>> tyyppi (t)

Tuple on muuttumaton, vaikka se sisältää muutettavan objektin, luettelon.

Vertaa tätä merkkijonoon, jossa olemassa olevan taulukon muuttaminen muuttaa objektia (koska merkkijonot ovat muuttumattomia).

>>> x = "abc"
>>> tunnus (x)
4371437472
>>> x + = "d"
>>> x
'Abcd'
>>> tunnus (x)
4373053712

Nimi x on sidottu tässä toiseen tyyppimerkkijonoon. Tämä muuttaa myös tunnuksensa.

Alkuperäinen esine, joka on pysyvä, pysyy muuttumattomana. Sidonta selitetään tarkemmin alla, jonka pitäisi tehdä asiat selkeämmiksi.

Sisäänrakennetut tyypit

Pythonissa on useita sisäänrakennettuja tyyppejä:

Ei mitään

Tyyppiä edustaa yksi objekti, siis yksi arvo. Ainoa objekti, jonka tyyppi = NoneType

>>> tyyppi (ei mitään)

numerot

Tämä on kokoelma abstrakteja perusluokkia, joita käytetään numeroiden esittämiseen. Niitä ei voida hetkellistää, ja int, float perivät numeroista.Numero.

Ne luodaan numeerisilla kirjaimilla ja aritmeettisilla operaatioilla. Palautetut esineet ovat muuttumattomia, kuten olemme nähneet. Seuraavat esimerkit tekevät tämän selväksi:

>>> a = 3 + 4
>>> tyyppi (a)

>>> isinstance (a, numerot.Numero)
Totta
>>> isinstance (a, numerot.Integroitu)
Totta
>>> jatkuvuus (3,14 + 2j, numerot.Real)
Väärä
>>> jatkuvuus (3,14 + 2j, numerot.kompleksi)
Totta

sekvenssit

Ne edustavat äärellisiä järjestettyjä joukkoja, jotka on indeksoitu ei-negatiivisilla kokonaislukuilla. Aivan kuten joukko muita kieliä.

len () palauttaa sekvenssien pituuden. Kun pituus on n, hakemistojoukossa on elementtejä välillä 0 ... n-1. Sitten seitsemäs elementti valitaan sekvenssillä [i-1].

Jaksolle l voit valita hakemistojen välillä elementtejä viipaloimalla: l [i: j].

Jaksoja on kahta tyyppiä: muuttuva ja muuttumaton.

  • Muuttamattomia sekvenssejä ovat: merkkijonot, tuples ja tavut.
  • Muutettaviin sekvensseihin kuuluvat: luettelot ja tavumallit

sarjat

Ne edustavat järjestämättömiä, äärellisiä joukkoja ainutlaatuisia, muuttumattomia esineitä. Niitä ei voida indeksoida, mutta ne voidaan toistaa. len () palauttaa silti sarjan kohteiden määrän.

Sarjoja on kahta tyyppiä: muuttuvat ja muuttumattomat.

  • Setti () luo muutettavan joukon.
  • Frozenset () on luonut muuttumattoman joukon.

kartoituksia

Sanakirja

Ne edustavat äärellisiä joukkoja esineitä, jotka on indeksoitu melkein mielivaltaisilla arvoilla. Avaimet eivät voi olla muutettavissa olevia esineitä. Tähän sisältyy luetteloita, muita sanakirjoja ja muita objekteja, joita verrataan arvon perusteella, ei objektiidentiteetin perusteella.

Tämä tarkoittaa, että frozenset voi olla myös sanakirja-avain!

moduulit

Moduuliobjekti on Python-organisaation perusyksikkö. Nimitila toteutetaan sanakirjana. Attribuuttiviitteet ovat hakuja tästä sanakirjasta.

Moduulille m sanakirja on vain luku -tyyppinen, m. __ dict__ käyttää sitä.

Se on tavallinen sanakirja, joten voit lisätä siihen avaimia!

Tässä on esimerkki Zen of Pythonista:

Lisäämme moduuliin mukautetun toiminnon, kuvan ().

>>> tuo tämä nimellä t
>>> t .__ dict__
{'__name__': 'this', '__doc__': Ei mitään, '__package__': '',
.....
.....
':': "Gur Mra bs Clguba, ol Gvz Crgref \ n \ nOrnhgvshy vf orggre guna
vqrn. \ nAnzrfcnprf her bar ubaxvat terng vqrn - yrg'f qb zber bs gubfr! ",
'd': {'A': 'N', 'B': 'O', 'C': 'P', 'D': 'Q', 'E': 'R', 'F': ' S',
'u': 'h', 'v': 'i', 'w': 'j', 'x': 'k', 'y': 'l', 'z': 'm'},
'c': 97,
'i': 25
}
>>> def kuva ():
... tulosta ("Voitko selvittää Pythonin Zenin?")
...
>>> t.fig = kuva
>>> t.fig ()
Voitko selvittää Pythonin Zenin?
>>> t .__ dict__
{'__name__': 'this', '__doc__': Ei mitään, '__package__': '',
.....
.....
':': "Gur Mra bs Clguba, ol Gvz Crgref \ n \ nOrnhgvshy vf orggre guna
vqrn. \ nAnzrfcnprf her bar ubaxvat terng vqrn - yrg'f qb zber bs gubfr! ",
'd': {'A': 'N', 'B': 'O', 'C': 'P', 'D': 'Q', 'E': 'R', 'F': ' S',
'u': 'h', 'v': 'i', 'w': 'j', 'x': 'k', 'y': 'l', 'z': 'm'},
'c': 97,
'i': 25
'viikuna': 
}
>>> tulosta ("". liity ([t.d.get (c, c) c varten t.s]))
Pythonin Zen, kirjoittanut Tim Peters
Kaunis on parempi kuin ruma.
Täsmällinen on parempi kuin epäsuora.
Yksinkertainen on parempi kuin monimutkainen.
Monimutkainen on parempi kuin monimutkainen.
Litteä on parempi kuin sisäkkäinen.
Harva on parempi kuin tiheä.
Luettavuus laskee.
Erityistapaukset eivät ole tarpeeksi erityisiä rikkomaan sääntöjä.
Vaikka käytännöllisyys voittaa puhtauden.
Virheiden ei tulisi koskaan tapahtua hiljaa.
Ellei nimenomaisesti ole vaiennettu.
Kieltäydy kiusauksesta arvata epäselvyyden edessä.
Niitä pitäisi olla yksi - ja mieluiten vain yksi - selkeä tapa tehdä se.
Vaikka tämä tapa ei välttämättä ole aluksi ilmeistä, ellet ole hollantilainen.
Nyt on parempi kuin ei koskaan.
Vaikka koskaan ei ole usein parempi kuin * nyt *.
Jos toteutusta on vaikea selittää, se on huono idea.
Jos toteutusta on helppo selittää, se voi olla hyvä idea.
Nimitilat ovat yksi hieno idea - tehkäämme enemmän niitä!

Ei myöskään kovin hyödyllinen, mutta hyvä tietää.

Operaattorin ylikuormitus

Python mahdollistaa käyttäjän ylikuormituksen.

Luokilla on erityiset toimintonimet - menetelmät, joita ne voivat käyttää Pythonin määriteltyjen operaattoreiden käyttämiseen. Tähän sisältyy viipalointi, aritmeettiset operaatiot ja tilaus.

Esimerkiksi __getitem __ () viittaa tilaamiseen. Siksi x [i] vastaa tyyppiä (x) .__ getitem __ (x, i).

Siksi operaattorin [] käyttämiseksi luokassa someClass: sinun on määritettävä __getitem __ () jollain luokalla.

>>> luokan operaattori (testi):
... valsi = [1,2,3,4]
... def __getitem __ (itse, i):
... palauta itsearvot [i]
...
>>> x = operatorTest ()
>>> x [2]
3
>>> x .__ getitem __ (2)
3
>>> tyyppi (x)

>>> tyyppi (x) .__ getitem __ (x, 2)
3
>>> OperatorTest .__ getitem __ (x, 2)
3

Hämmentyneitä siitä, miksi ne kaikki ovat vastaavia? Se on seuraava osa - missä käsittelemme luokan ja funktion määritelmät.

Samoin __str __ () -toiminto määrittää lähdön, kun str () -menetelmää kutsutaan luokan objektiin.

Vertailutoimenpiteitä varten erityisten toimintojen nimet ovat:

  • objekti .__ lt __ (itse, muu) <(”alle”)
  • objekti .__ le __ (itse, muu) <= (”pienempi tai yhtä suuri”)
  • objekti .__ eq __ (itse, muu) = = (”yhtä suuri”)
  • object .__ ne __ (itse, muu) for! = (“ei yhtä suuri”)
  • objekti .__ gt __ (itse, muu) kohteelle> (“suurempi kuin”)
  • objekti .__ ge __ (itse, muu) haulle> = (“suurempi tai yhtä suuri”)

Joten esimerkiksi x

Aritmeettisille operaatioille on myös erityisiä toimintoja, kuten objekti .__ add __ (itse, muu).

Esimerkiksi x + y kutsutaan nimellä x .__ add __ (y)

Toinen mielenkiintoinen toiminto on __iter __ ().

Kutsut tätä menetelmää, kun tarvitset iteraattorin säilölle. Se palauttaa uuden iteraattoriobjektin, joka voi iteroida kaikkien säilössä olevien objektien yli.

Kartoituksissa sen tulisi toistua säiliön näppäimien yli.

Itseratorio-objekti tukee kahta menetelmää:

  • iterator .__ iter __ (): Palauttaa itse objektin.

Tämä tekee iteraattoreista ja säilöistä vastaavat.

Tämän avulla iteraattoria ja säilöjä voidaan käyttää sekä lauseissa että lauseissa.

  • iteraattori .__ seuraava __ (): Palauttaa seuraavan kohteen säilöstä. Jos muita kohteita ei ole, nostetaan StopIteration -poikkeus.
luokka IterableObject (object): # Iteraattoriobjektiluokka
     vals = []
     se = 0
     def __init __ (itse, val):
         itsearvot = val
         se = 0
 
     def __iter __ (itse):
         palata itse
 
     def __seuraava __ (itse):
         jos self.it 
>>> iter_object_example = IterableObject ([1,2,3])
>>> varten val iter_object_example:
... tulosta (val)
...
1
2
3
>>> iter_container_example = IterableClass ()
>>> varten val iter_container_example:
... tulosta (val)
...
1
2
3
4

Hienoja juttuja, eikö niin? Javascriptissa on myös suora vastine.

Kontekstinhallinta toteutetaan myös operaattorin ylikuormituksen avulla.

avoimella (tiedostonimi, 'r') kuten f

open (tiedostonimi, 'r') on kontekstinhallintaobjekti, joka toteuttaa

objekti .__ kirjoita __ (itse) ja

objekti .__ poistuminen __ (itse, exc_type, exc_value, trackback)
Kaikki yllä olevat kolme parametria ovat tyhjät, kun virhe on Ei mitään.

luokka MyContextManager (objekti):
    def __init __ (itse, jotkut_tuotteet):
        self.object_to_manage = jotkut_jutut
    def __enter __ (itse):
        print ("Kontekstinhallinnan aloittaminen")
        return self.object_to_manage # voi myös tehdä joitain muunnoksia
    
    def __exit __ (itse, exc_type, exc_value, trackback):
        jos exc_type ei ole:
            tulosta ("Poistettu onnistuneesti")
            # Muut suljettavat asiat
>>> MyContextManager -sovelluksella ("tiedosto") nimellä f:
... tulosta (f)
...
Kontekstinhallinnan aloittaminen
tiedosto
Poistunut onnistuneesti

Tämä ei ole hyödyllinen - mutta saa asian ymmärtämään. Onko siitä joka tapauksessa hyötyä?

Philosoraptor

Suoritusmalli

Lohko on koodinpala, joka suoritetaan yksikönä suorituskehyksessä.

Esimerkkejä lohkoista ovat:

  • Moduulit, jotka ovat ylätason lohkoja
  • Toiminto runko
  • Luokan määritelmä
  • Mutta EI silmukoille ja muille ohjausrakenteille

Muista kuinka kaikki on esine Pythonissa?

No, sinulla on nimet sidottu näihin esineisiin. Nämä nimet ovat mitä ajattelet muuttujina.

>>> x
Jäljitys (viimeisin puhelu viimeksi):
  Tiedosto "", rivi 1, 
NameError: nimeä 'x' ei ole määritelty

Nimen sitominen tai osoittaminen tapahtuu lohkossa.

Esimerkkejä nimien sitomisesta - nämä ovat intuitiivisia:

  • Funktion parametrit on sidottu funktiossa määriteltyihin nimiin
  • Tuo lauseet sitovat moduulin nimen
  • Luokka- ja funktiomääritelmät sitovat nimen luokka- / toimintoobjekteihin
  • Kontekstinhallinta: jossa ... as f: f on objekti, joka sitoo ... objektia

Lohkoon sidotut nimet ovat paikallisia kyseiselle lohkolle. Tämä tarkoittaa, että globaalit muuttujat ovat yksinkertaisesti moduuliin sidottuja nimiä.

Lohkossa käytettyjä muuttujia, joita ei ole määritelty, on vapaita muuttujia.

Alueet määrittelevät nimen näkyvyyden lohkossa. Muuttujan laajuus sisältää sen lohkon, johon se on määritelty, samoin kuin kaikki määrittelevän lohkon sisällä olevat lohkot.

Muistatko kuinka silmukoita ei estä? Siksi silmukkaan määritellyt iterointimuuttujat ovat käytettävissä silmukan jälkeen, toisin kuin C ++ ja JavaScript.

>>> i: lle alueella (5):
... x = 2 * i
... tulosta (x, i)
...
0 0
2 1
4 2
6 3
8 4
>>> tulosta (x, i) # silmukan ulkopuolella! x määritettiin sisällä.
8 4

Kun nimeä käytetään lohkossa, se ratkaistaan ​​käyttämällä lähintä suljettua laajuutta.

Huomaa: Jos nimien sitomistoiminto tapahtuu missä tahansa koodilohkon sisällä, kaikkia nimessä olevia käyttöjä lohkossa käsitellään viitteinä nykyiseen lohkoon. Tämä voi johtaa virheisiin, kun nimeä käytetään lohkossa ennen kuin se sidotaan.

Esimerkiksi:

>>> name = "external_scope"
>>> def foo ():
... nimi = "sisäinen toiminto", jos nimi == "ulompi_näyttö" \
                muuten "not_inner_function"
...
>>> foo ()
Jäljitys (viimeisin puhelu viimeksi):
  Tiedosto "", rivi 1, 
  Tiedosto "", rivi 2, foo
UnboundLocalError: paikallinen muuttuja 'name', johon viitataan ennen tehtävää

Tämä on upea jäljitys, jonka pitäisi olla järkevää nyt.

Meillä on ylimmän tason moduuli, moduuli - jossa on toinen lohko, toiminto. Jokaisella toiminnon sisällä olevalla sidonnalla on tehtävä sen ylimmällä tasolla!

Siksi, kun sidot nimen nimen objektiin "inner_function": ennen sidontaa tarkistat sen arvon. Sääntö sanoo, että et voi viitata siihen ennen sidontaa. Tarkka syy UnboundLocalError-syylle.

Eikä tällainen toteutusmalli? Lähde

Leksinen analyysi

Python antaa sinun käyttää riviliitoksia. Jatka rivejä nimenomaisesti käyttämällä viivaa.

Kommentteja ei sallita riviliitosten jälkeen.

jos a <10 ja b <10 \ # kommentti johtaa SyntaxErroriin
ja c <10: # Kommentti kunnossa
    palata totta
else:
    palaa väärin

Epäsuorasti linjan liittyminen tapahtuu yksinään, kun elementit ovat olkainten sisällä. Kommentit tässä ovat sallittuja.

month_names = ['Januari', 'Februari', 'Maart', # Nämä ovat
               'Huhtikuu', 'Mei', 'Juni', # hollantilaiset nimet
               'Juli', 'Augustus', 'September', # kuukausien ajan
               'Lokakuu', 'marraskuu', 'joulukuu'] vuoden numero

sisennys

Välien / välilehteiden määrällä sisennyksessä ei ole merkitystä, kunhan se kasvaa asioissa, jotka olisi sisennettävä. Ensimmäistä riviä ei tule sisennä.

Neljän välilyönnin sääntö on määritelty PEP 8: Style Guide -standardissa. On hyvä käytäntö noudattaa sitä.

# Laske luettelo kaikista l: n permutaatioista.
def perm (l):
        # Kommenttien sisennys jätetään huomioimatta
    jos len (l) <= 1:
                  paluu [l]
    r = []
    i: lle alueella (len (l)):
             s = l [: i] + l [i + 1:] # Syvennys valittu
             p = perm (s) # Täytyy olla samalla tasolla kuin yllä
             x: lle p: ssä:
              r.append (l [i: i + 1] + x) # Yksi välilyönti kunnossa
    paluu r

On myös muutama varattu tunniste.

  • _ tuontia varten: funktioita / muuttujia, jotka alkavat merkillä _, ei tuoda.
  • __ * __ järjestelmän määrittelemille nimille, määritelty toteutuksen avulla: olemme nähneet muutamia näistä. (__str __ (), __iter __ (), __add __ ())

Python tarjoaa myös implisiittisen merkkijonon liitoksen

>>> def name ():
... palauta "Neil" "Kakkar"
...
>>> nimi ()
'Neil Kakkar'

Alusta merkkijonot

Merkkijonojen muotoilu on hyödyllinen työkalu Pythonissa.

Merkkijonoissa voi olla {expr} merkkijonossa, missä lause on lauseke. Lausekkeen arviointi korvataan paikallaan.

Tulokset voidaan määritellä muuntamaan tulos ennen muotoilua.

! r puhelut repr (),! puhelut str () ja! a vaatii ascii ()

>>> nimi = "Fred"
>>> f "Hän sanoi, että hänen nimensä on {nimi! r}."
"Hän sanoi, että hänen nimensä on" Fred "."
>>> f "Hän sanoi, että hänen nimensä on {repr (nimi)}." # repr () on ekvivalentti. to! r
"Hän sanoi, että hänen nimensä on" Fred "."
>>> leveys = 10
>>> tarkkuus = 4
>>> arvo = desimaali.Deimaali ("12.34567")
>>> f "tulos: {arvo: {leveys}. {tarkkuus}}" # sisäkkäisiä kenttiä
'tulos: 12.35'
# Tämä on sama kuin "{decf: 10.4f}" .muoto (decf = kelluva (arvo))
>>> tänään = päiväaika (vuosi = 2017, kuukausi = 1, päivä = 27)
>>> f "{tänään:% B% d,% Y}" # # käyttämällä päivämäärämuotoa
'27. tammikuuta 2017'
>>> numero = 1024
>>> f "{numero: # 0x}" # käyttämällä kokonaislukuformaattia
'0x400'

Se on puhtaampi syntaksi str.format () -sovelluksen käyttöön

Yhteenveto

Tämän avulla olemme peittäneet Pythonin tärkeimmät pylväät. Objektitietomalli, suoritusmalli sen laajuuksilla ja lohkoilla ja jotkut bitit merkkijonoissa. Kaiken tämän tietäminen vie sinut jokaisen kehittäjän eteen, joka tietää vain syntaksin. Se on suurempi määrä kuin luulet.

Osassa 2 tarkastellaan esinepohjaisia ​​luokkia ja toimintoja.

Lisätietoja tästä on hieno kirja - Tehokas Python.
[Kumppanilinkki - kiitos tukemisesta!]

Muut tämän sarjan tarinat:

  • Kuinka ei enää pelätä Vimaa
  • Kuinka ei enää pelätä GIT: tä

Nautitko tästä? Älä missaa viestiä uudelleen - tilaa postituslistani!