Python intro

(cc) Tore Gaupseth 16.03.2016 21:44:12
Innledning
Python som kalkulator
Talltyper
Variabler
Datastrukturer
Stringer
Lister
Tupler
Oppslagslister
Innlesing og utskrift
Moduler, navneområder
Funksjoner, klasser og objekter

Innledning

Python er ...

Python 2.x vs 3.x

I heftet er det vist eksempler kopiert inn fra fra arbeidsflaten i Python, noen ganger med små kommentarer som forklaring,

>>> for n in range(3):                 # for hver n i området [0, 2]
...     print(n)
0
1
2

Du får best utbytte av kurset ved å ha startet opp Python og prøve ut kommandoene som blir vist i stedet for bare å lese teksten. Bruk klipp/lim fra kodeeksemplene. Lag dine egne varianter og se hva som skjer. Når mine knappe forklaringer ikke er tilstrekkelige vil du finne utfyllende hjelp bak noen tastetrykk i Python. I avsnittene som er merket Gjør det selv finner du treningsoppgaver som du kan prøve deg på.

Siden dette er en nettside kan du bruke søkefunksjonen Ctrl+F, F3 i nettleseren til å finne nøkkelord.

  1. Skaff deg Python og installer programvaren. Hvis dette er ditt første møte med Python kan det kanskje være greit å installere den komplette pakken Anaconda.
  2. Pythons originale An Informal Introduction to Python er ent grei starthjelp.
  3. Så kan du kanskje fortsette med A Crash Course in Python for Scientists.

Bakgrunnen til dette heftet er at

Python som kalkulator

Talltyper

Tall er enten heltall, flyttall (desimaltall) eller komplekse tall. Regneuttrykk med heltall og flyttall blir flyttall. Komplekse tall bruker 1j som imaginær enhet.

    integer    heltall, telletall
    float      flyttall, desimaltall
    complex    komplekse tall
>>> 6-5*4+3**2                         # Et regnestykke med heltall,
-5                                     # svaret blir heltall
>>> 1+2*3-4/5                          # Men, divisjon mellom heltall gir float
6.2

Kommandoer tastes inn etter promptet >>> og svaret vises på neste linje. Kommentarer starter med et hashtegn # og gjelder resten av linja.

Evaluering skjer fra venstre mot høyre, men presedens overstyrer, operasjoner på høyere nivå utføres før operasjoner på lavere nivå. Uttrykk i parenteser beregnes først.

    1.   ( )             Parenteser
    2.   **              Eksponenter
    3.   +, -            Fortegn, pos, neg
    4.   *, /, //, %     Multiplikasjon, divisjon, heltallsdivisjon, rest
    5.   + -             Addisjon og subtraksjon

Her er noen regnestykker som belyser evaluering og presedens,

>>> -2**3                              # Eksponentoperator ** har høyere presedens enn fortegn
-8
>>> 8+5-6/2/3**-2+1                    # 13 - 3.0/(1/9) + 1 = -13.0
-13.0
>>> 8+(5-6/2)/3**-2+1                  # 8 + 2.0/(1/9) + 1 = 27.0
27.0

Divisjon mellom heltall gir altså flyttall som resultat. Noen ganger ønsker vi å la svaret bli heltall ved at det rundes ned til nærmeste heltall. En heltallsdivisjon vil dermed gi hvor mange hele ganger divisor går opp i dividend. Her viser vi at $\frac {44}{3} = 14 + \frac 2 3$,

>>> 44 // 3                            # Heltallsdivisjon
14
>>> 44 % 3                             # Rest etter heltallsdivisjon
2
>>> 3*(44//3)+44%3
44

Komplekse tall på komponentform bruker 1j eller 1J som imaginær enhet. Her er noen operasjoner,

>>> 3+4j
(3+4j)
>>> (3+4j)/(1-2j)                      # Matematikk med komplekse tall
(-1+2j)
>>> abs(3+4j)                          # Absoluttverdi
5.0
>>> (3+4j).real                        # Reell komponent
3.0
>>> (3+4j).imag                        # Imaginær kommponent
4.0
>>> (3+4j).conjugate()                 # Kompleks konjugert
(3-4j)
>>> complex(3, 4)                      # Lager kompleks tall med konstruktørfunksjon
(3+4j)

Her møter du plutselig de grunnleggende byggesteinene i Python som objektorientert programmeringsspråk - funksjoner, objekter med attributter, metoder og konstruktører. Alt dette blir forklart i detalj utover i kurset, men her en ultrakort oversikt i Pythons egen sjargong. Alle dataverdier vi opererer med er objekter som har visse egenskaper, attributter, metoder og konstruktører. Den siste linja, complex(3, 4) konstruerer (oppretter) et objekt av klassen (datatypen) complex, med de to parametrene 3 og 4 som verdier på reell- og imaginær attributt. Den første linja, 3+4j konstruerer et komplekst tall med en kortform. Linja med (3+4j).imag leser av attributten imag i objektet. Linja med (3+4j).conjugate() bruker objektets metode conjugate() til å gi den kompleks konjugerte verdien av objektet. Absoluttverdien (lengden) av et komplekst tall finner vi med funksjonen abs().

Python kan sjonglere med vanskeligere matteoppgaver enn de vi har sett her. Ved å hente inn definisjoner fra moduler som math, cmath, nympy, scipy og sympy kan vi utføre avansert matematikk. Se kurset SymPyIntro.

Variabler

En variabel er et navn som refererer til en verdi. Tall og andre dataverdier tilordnes variabler med operatoren likhetstegn, =. Det gir den fordelen at verdier kan brukes på nytt uten å taste inn hele regnestykket. Lag navn på variablene som forteller hva de står for. Skal vi regne ut arealet for et rektangel med gitt bredde og høyde kan vi for eksempel bruke bredde for gbredde, hoyde for høyde og areal for area. Her beregnes arealet av et rektangel med bredde=4 og høyde=3,

>>> bredde = 4
>>> hoyde = 3
>>> areal = bredde * hoyde
>>> areal
12.0

De to første programsetningene er tilordninger, de lar navnene bredde og hoyde referere til verdiene 4 og 3. Den tredje setningen lar navnet areal referere til resultatet av beregningen bredde * hoyde. I den siste linja ser vi at om vi gir selve variabelnavnet som kommando vil det vise verdien det refererer til.

Likhetstegnet brukes altså som tilordningsoperator i SymPy i setninger som

    variabelnavn = verdi eller uttrykk

der verdien eller resultatet av beregningen på høyre side blir lagret og gitt variabelnavnet på venstre side, slik at for eksempel en setning som

    alder = alder + 1

virker snodig hvis det feilaktig leses som en matematisk likning, men som tilordning betyr det at verdien som variabelen alder refererer til økes med 1. En tilordning som radius = 3 leses som 'radius tilordnes 3' eller 'radius får verdien 3'.

Variabelnavn må begynne med en bokstav og være uten mellomrom eller særnorske bokstaver. Med tegnet underscore kan vi lage oppdelte navn, for eksempel svar_5_b . Python skiller mellom store og små bokstaver. Resultatet av siste utførte beregning blir automatisk lagt i variabelen _ (underscore).

Python tillater flere tilordninger i samme linje. Uttrykk på høyre side evalueres først fra venstre mot høyre, deretter tilordnes de til variablene på venstre side.

>>> a, b = 1, 2                        # a=1, b=2
>>> a, b = b, a+b                      # a=b=2, b=a+b=1+2=3
>>> a
2
>>> b
3

Datastrukturer

Stringer, lister, tupler (tuples) og oppslagslister (dictionaries) er sekvensielle datatype som lagrer verdier i tabellform. Stringer og tupler defineres med dataverdier som ikke kan endres. Indekseringene starter med 0 som første element. ?? Legg merke til bruken av de forskjellige parentestypene. Hakeparenteser brukes ved indeksering. I matematikk vil funksjoner som finner flere løsninger gi disse i en liste. ??

Stringer

>>> navn = 'Abraham'                       # string
>>> navn[0]
'A'
>>> navn[0]= 'B'
#...
TypeError: 'str' object does not support item assignment

Når vi skal lage utskrift av beregninger ønsker vi å sette sammen en tekst som består av ord og tallverdier. Hvis en variabel areal inneholder verdien 12 ønsker vi at


Lister

>>> oddetall = [1, 3, 5, 7]                # list
>>> oddetall[2]= 9
>>> oddetall
[1, 3, 9, 7]

Tupler

>>> nevoer = ('Ole', 'Dole', 'Doffen')     # tuple
nevoer[1] = 'Petter'                   
#...
TypeError: 'tuple' object does not support item assignment

Oppslagslister

>>> persondata = {'fornavn': 'Donald', 'etternavn': 'Duck', 'alder': 78}
>>> persondata['alder'] = 89
>>> persondata
{'alder': 89, 'fornavn': 'Donald', 'etternavn': 'Duck'}

Innlesing og utskrift

Den enkleste måten å lage utskrift av en variabelverdi er å gi variabelnavnet som kommando. Vil vi styre litt mer av hva som skal vises bruker vi funksjonen print(), enten med en tallvariabel- eller med en string som argument.

>>> vekt = 75
>>> hoyde = 175
>>> bmi = vekt/(hoyde/100)**2
>>> bmi
24.489795918367346

Moduler, navneområder

Moduler er samlinger av Python kode som utfører spesialiserte oppgaver. Modulene inneholder definisjoner av variabler, konstanter, funksjoner og klasser. Noen moduler, som math og cmath, følger med i standard installasjon av Python, andre må installeres separat, for eksempel SymPy. Når vi skal ta i bruk en modul må vi enten importere den som et eget navneområde (namespace), eller legge den inn i det gjeldende navneområdet.

>>> sqrt(8)                            # Funksjonen sqrt er ikke med i standard Python
#...
NameError: name 'sqrt' is not defined
>>> import math                        # Leser inn modulen math
>>> math.sqrt(8)                       # Bruker sqrt fra navneområdet math
2.8284271247461903
>>> from math import *                 # Lar math bli med i gjeldende navneområde
>>> sqrt(8)
2.8284271247461903
>>> from sympy import *                # Leser inn sympy til gjeldende navneområde
>>> sqrt(8)                            # Bruker sqrt fra sympy
2*sqrt(2)

Symbolsk matematikk hentes fra modulen sympy. Symbolske regneuttrykk må lages som stringer til funksjonen S eller med symbolske variable.

>>> from sympy import *
>>> S('1/2 + 1/3')                     # S = sympify
5/6
>>> x = symbols ('x')                  # definerer symbolsk variabel
>>> 6*x-5-4*x+3
2*x - 2

Funksjoner, klasser og objekter

En funksjon er et stykke Python kode som utfører en avgrenset oppgave, for eksempel å finne kvadratrota av et tall. Når vi bruker funksjonen gjør vi et funksjonskall av formen funksjonsnavn(inngangsverdi), der vi gjerne sender med en (eller flere) inngangsverdier. Funksjonen lager et resultat og sender det tilbake til programkjøringen i form av en returverdi.

>>> def rot(x):                        # Dette er Python kode
        return x**(1/2)                # som definerer en funksjon

>>> rot(4)                             # Her er et funksjonskall
2.0                                    # som gir denne returverdien

Funksjonen rot som ble laget ovenfor eksisterer bare så lenge Pythonskallet kjører, men om linjene legges i en fil som lagres med filnavn navn.py, vil vi kunne bruke funksjonen senere ved å importere navn som en modul.

En klasse (class) er en samling funksjoner og variabler som beskriver en datatype. Vi har allerede møtt klassene heltall, komplekse tall, stringer, lister og andre. Et objekt er en enkelt instans (individ) av en klasse, på samme måte som at 'Tja' er et objekt av klassen string.

I modulene ligger det klassedefinisjoner som naturlig hører sammen. Vi henter et eksempel på modulen cmath som håndterer matematikk med komplekse objekter (tall). La oss sette opp to tall, w og z, og gjøre noen sjongleringer.

Noen datatyper og operasjoner med disse er altså innebygget i Python. Når vi bruker Python som kalkulator blir det ikke så mye snakk om klasser og objekter. La oss sette opp to komplekse tall, w og z, og gjøre noen sjongleringer.

>>> w = complex(3, -4)                 # Vi 'konstruerer' objektet w av klassen complex
>>> z = 2 + 1j                         # Objektet z konstrueres med kortform
>>> w+z                                # Enkel matematikk fungerer
(5-3j)
>>> z.imag                             # Henter ut imaginærverdien av z
1
>>> w.conjugate()                      # Bruker klassemetoden conjugate() til å hente konjugert verdi av w
(3+4j)
>>> w                                  # Men, w er ikke endret
(3-4j)
>>> abs(w)
5.0

Her var det mye på en gang. Selve klassenavnet brukes som konstruktør, objektet w av klassen complex settes opp (konstrueres) i linja w = complex(3, 4) med komponentene 3 og 4 som innverdier. Vi ser at komplekse tall er innebygget som klasse i Python. Derfor er det også laget en mulighet til å taste inn et komplekst tall på kortform, z=2+1j, som alternativ til formell konstrutør. Det samme gjelder også tall, der 7 blir et objekt av heltallsklassen, mens 7.0 blir et objekt av float-klassen.

Et objekt har gjerne dataverdier som ligger lagret i attributter. Det har også funksjoner som gjør det i stand til å sjonglere med attributtene. Imaginærverdien av z kan vi finne ved å legge .imag bak objektnavnet, z.imag. Den konjugerte verdien av w kan vi finne ved å tilkalle metoden (funksjonen) conjugate, w.conjugate(). Legg merke til forskjellene her, z.imag henter ut en dataverdi fra objektet, mens w.conjugate() gjør en operasjon på objektet. Til slutt bruker vi funksjonen abs til å finne absoluttverdien (lengden) av w. Denne funksjonen er altså laget slik at den kan operere med objekter.

Vi går litt videre og onsker å finne kavdratrota av z, og prøver med funksjonen sqrt,

>>> sqrt(w)
Traceback (most recent call last):
  File "<pyshell#100>", line 1, in <module>
    sqrt(w)
NameError: name 'sqrt' is not defined

Neivel, kanskje ble det litt for avansert for standard Python, la oss importere modulen cmath,

>>> import cmath
>>> cmath.sqrt(w)                      # Bruker funksjonen sqrt i modulen cmath
(2+1j)
>>> _**2                               # Tester siste svar om vi virkelig fant kvadratrot
(3+4j)

Her brukes funksjonen sqrt som er definert i modulen cmath til å beregne kvadratrota av det komplekse tallet w. Vi må altså henvise til funksjoner i en importert modul med 'modulnavn.'. En annen måte å gjøre det samme på er altså å importere alle funksjoner i cmath inn i det gjeldende navneområdet. Da bruker vi funksjonsnavnene direkte,

>>> from cmath import *
>>> sqrt(w)
(2+1j)
>>> z.conjugate().imag * sqrt(w)
(-2-1j)