1. Tips

Programmeringsspråken har många likheter. Har man lärt sig ett programmeringsspråk är det lättare att lära sig ett nytt för man har lärt sig tänket. även om syntaxen kan se lite annorlunda ut.
Hittills, i programmering 1, har vi lärt oss generella saker som kan användas i nästan alla programmeringsspråk även om syntaxen kan se lite annorlunda ut.

I det här kapitlet kommer vi att titta på lite mer avancerad saker som är speciella för Python, men där några av tipsen även kan göras på olika sätt i andra programmeringsspråk.

Här presenteras 18 tips som gör att du lättare kan förstå och skriva mer avancerad kod i Python.
1.1 Kommentarer (multiline comment)
1.2 Jämförelser (chained comparison)
1.3 Tilldelning av flera variabler (multiple assignment)
1.4 Unpacking
1.5 Returnera flera värden (return multiple values)
1.6 Understreck som loop-variabel (underscore as loop iterator)
1.7 Else-gren i for- och while-satsen
1.8 Tilldelning i uttryck, t.ex. i if- och while-satser (assignment in expression)
1.9 Förkortade if-satser (ternary condition)
1.10 Onödiga temporära variabler
1.11 Kedjning (chaining)
1.12 Default-parametrar
1.13 Namnge argument (keyword arguments)
1.14 Datatyper på parametrar (type hints)
1.15 Args
1.16 List comprehension
1.17 Lägga till element i en tuple
1.18 Anonyma funktioner (lambda)
1.19 Exempel på användning av tipsen

 

1.1 Kommentarer (multiline comment)

För att kommentera resten av raden används #

# This is a single line block comment
a = 1  # This is a single line inline comment
print(a)

För att kommentera ett helt stycke, dvs flera rader, används ''' eller """

'''
This is a
multiline
comment
''' 


"""
This is also a
multiline
comment
"""

 

1.2 Jämförelser (chained comparison)

Att jämföra en variabel mot två olika värden i ett uttryck görs ofta med den logiska operatorn and.

if result >= 0 and result <= 15:
    x = 10

I Python finns även ett snabbare sätt att göra samma sak

if 0 <= result <= 15:
    x = 10

 

1.3 Tilldelning av flera variabler (multiple assignment)

I Python kan man tilldela flera variabler värden i samma sats.

Det går att tilldela flera variabler samma värde

# Several variables get the same value
a = b = c = 2
print(f'{a} {b} {c}')

Det går också att använda följande kod för att tilldela flera variabler samma eller olika värden i samma sats

# Several variables get the same value
a, b, c = 2, 2, 2
print(f'{a} {b} {c}')

# Several variables get different values
x, y, z = 1, 2, 3
print(f'{x} {y} {z}')

För att två variabler ska byta värden brukar en temporär variabel införas.

a, b = 5, 3 
print(f'Values before swap: a={a}, b={b}')
tmp = a
a = b
b = tmp
print(f'Values after swap: a={a}, b={b}')

I Python går det att göra bytet av värden i en sats.

a, b = 5, 3 
print(f'Values before swap: a={a}, b={b}')
a, b = b, a
print(f'Values after swap: a={a}, b={b}')

 

1.4 Unpacking

Att tilldela variabler värden från samlingar, t.ex. listor, kan göras enklare med unpacking.

# Assign variables values from a list
lst = [2, 4, 6]
x = lst[0]
y = lst[1]
z = lst[2]
print(f'x = {x], y = {y}, z = {z}')
# Use unpacking to assign variables values from a list 
lst = [2, 4, 6]
x, y, z = lst
print(f'x = {x], y = {y}, z = {z}')
# Use unpacking to assign variables values from a tuple
tup = (1, 2, 3)
x, y, z = tup
print(f'x = {x], y = {y}, z = {z}')
# Use unpacking to assign variables values from a string
str = "cat"
x, y, z = str
print(f'x = {x], y = {y}, z = {z}')

 

1.5 Returnera flera värden (return multiple values)

Python kan på ett enkelt sätt returnera flera värden från en funktion på ungefär samma sätt som tilldelning av värden till flera variabler.

def increment(a, b, c):
    a += 1
    b += 1
    c += 1
    return a, b, c
    
x, y, z = 1, 2, 3
print(f'Values before function call: x={x}, y={y}, z={z}')

x, y, z = increment(x, y, z)
print(f'Values before after function call: x={x}, y={y}, z={z}')

 

1.6 Understreck som loop-variabel (underscore as loop iterator)

En loop-variabel brukar ofta användas i loopen. Kallas också för iterator.

# Using the the loop variable i in the loop
for i in range(5):
    print(i, end=' ')

Men ibland används inte loop-variabeln i for-loopen. Då för att vara tydlig med det brukar _ (understreck) använda som loop-variabel.

# Not using the loop variabel in the loop, using variable name _ , which shows it's deliberately ignored
for _ in range(5):
    print('hello ', end=' ')

 

1.7 Else-gren i for- och while-satsen

I Python kan while-satsen ha en else-gren. Hur fungerar det?

# Both loop block and else block will be executed, not good
loop = True
while loop:
    print('loop while block')
    loop = False
else:
    print('loop else block')

För att undvika att både loop- och else-blocket utförs används break-satsen.
Bara else-grenen utförs om loop-villkoret är falskt i första iterationen

loop = False
while loop:
    print('loop while block')
    loop = False
    break
else:  
    print('loop else block')

Om loop-villkoret är sant i första iteration kommer ändå break-satsen hindra att else-blocket utförs.

loop = True
while loop:
    print('loop while block')
    loop = False
    break
else:
    print('loop else block')

Även for-satsen kan ha en else-gren och fungerar på samma sätt.

lst = [1, 3, 5]
for e in lst:
    if e % 2 == 0:
        print('There are at least one even number in the list')
        break
else:
    print('No even numbers in the list')
lst = [1, 3, 6]
for e in lst:
    if e % 2 == 0:
        print('There are at least one even number in the list')
        break
else:
    print('No even numbers in the list')
 

1.8 Tilldelning i uttryck, t.ex. i if- och while-satser (assignment in expression)

Det går inte att göra tilldelningar i villkor

a = 1
if a = 1:
    print('test')

Men med nyckelordet := går det faktiskt att fr.om. Python v3.8 (2019) göra en tilldelning i uttryck, t.ex. villkorsuttryck.

# Use an assignment in an if-statement
a = 1
print(f'a = {a}')
if (a := 2) * 3 == 6:
    print('test True')
else:
    print('test False')
print(f'a = {a}')

Följande exempel anropar en funktion och använder sedan returvärdet.

# Call a function and use the value in if-statement
ret = foo(a, b)
if ret > 10:  
    print(ret)

Om man inte vill använda temporär-variabeln ret skulle samma kod se ut som

# Replace the temporary variable ret with function calls
if foo(a, b) > 10:  
    print(foo(a, b))

Det är inte särskilt effektivt att behöva anropa funktionen 2 gånger utan koden kan skrivas smartare med hjälp av en tilldelning i if-satsen. Det går att lösa med en tilldelning och jämförelse i if-satsen.

# An assignment and comparison in an if-statement
if (ret := test(a, b)) > 10:
    print(ret)
 

1.9 Förkortade if-satser (ternary condition)

En vanlig if-sats

a, b = 2, 3
if a > b:
    x = 1
else:
    x = 4
print(f'x = {x}')

Det går att skriva samma if-sats i en förkortad variant (ternary condition).

a, b = 2, 3
x = 1 if a > b else 4
print(f'x = {x}')
 

1.10 Onödiga temporära variabler

Använd inte onödiga temporära variabler. T.ex. kan

a = 3 * b + 2
test = a * 3
skrivas som

test = (3 * b + 2) * 3
Temporära variabler ska bara användas då de ökar läsbarheten, dvs gör det lättare att läsa och förstå koden.

Funktionen

def test(a, b):
    if a > b:
        return a
    else:
        return b

kan man skriva som

def test(a, b):
    ret = a if a > b else b
    return ret

Men variabeln ret tilldelas först ett värde och i nästa sats returneras variabelns värde. Det går att enklare skriva som

def test(a, b):
    return a if a > b else b

 

1.11 Kedjning (chaining)

Kedjning (chaining)

a = foo()
b = a.line()
b.my_print()

# Kan skrivas "enklare" som
foo().line().my_print()
På första raden tilldelas ju a till foo(), så a och foo() är samma.
Så på rad 2, a.line(), kan ju a bytas ut mot foo() eftersom de är ju samma sak, dvs rad 2 blir då: b = foo().line()
På samma sätt i rad 3, b.my_print(), så är ju b samma sak som foo().line(), så b kan bytas ut mot foo().line().
Då blir rad 3: foo().line().my_print()

Denna teknik kallas för chaining eller kedjning på svenska där flera anrop och/eller satser kopplas ihop.

 

1.12 Default-parametrar

Om en funktion har en default-parameter (kallas ibland för standard-parameter) innebär det att funktionen kan anropas med färre antal argument än det finns parametrar.

# The function has an default parameter
def foo(a, b, c=2):
    return a + b + c

# The function called with 3 arguments	
ret = foo(1, 2, 3)
print(ret)

# The function called with 2 arguments
ret = foo(1, 2)
print(ret)
Om ett argument utelämnas i anropet får parametern default-värdet.

 

1.13 Namnge argument (keyword arguments)

Normalt har argumenten samma ordning som parametrarna, men genom att ange namnen på parametrarna kan parameterordningen ändras.

# Give some parameters default values
def print_foo(a, b, x=0, y=0, z=0):
    print(f'a={a}, b={b}, x={x}, y={y}, z={z}')


print_foo(1, 2)
print_foo(b=5, a=7)

Om vissa default-parametrar inte anges i anropet kan det vara viktigt att namge argumenten.

# Give some parameters default values
def print_foo(a, b, x=0, y=0, z=0):
    print(f'a={a}, b={b}, x={x}, y={y}, z={z}')


print_foo(1, 2, 3)    # x will get the value of 3
print_foo(1, 2, y=3) 
print_foo(1, 2, z=5)

Vi har tidigare använt kod som t.ex.

print('hej', end=' ')

Det beror på att print-funktionen är definierad enligt:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

I satsen print('hej', end=' ') anropas print-funktionen med 2 argument och där sep-parameterns default-värde används.

 

1.14 Datatyper på parametrar (type hints)

När funktioner definieras anges inte vilken datatyp parametrarna ska ha. Förhoppningsvis kan det framgå av bra beskrivande variabelnamn.

def takes_int_str(x, y):
    return x + 7

# Call the function with an int and a string
ret = takes_int_str(5, "A")

# Calling this function with a string as the first argument will cause an error
ret = takes_int_str("A", 5)

Faktiskt kan man i Python ge ledtråd om datatyper för parametrarna och returvärde genom "type hints".

# The function definition hints the datatypes of the parameters and return value
def takes_int_str(x: int, y: str) -> int:
  return x + 7

ret = takes_int_str(1, "A")
Fast ingen syntaxkontroll görs om datatyperna är korrekta utan det är mer som ledtråd (=hjälp) om de anges. Läs mer om type hints

 

1.15 Args

Den speciella syntaxen *args i funktionsdefinitioner används för att kunna skicka olika antal argument till en funktion. Det används för att kunna skicka argument m.h.a. listor med olika antal element. Syntaxen är att använda symbolen * (asterisk) för att kunna skicka in olika antal argument. Praxis är att använda namnet args.

# Function has variable number of parameters
def add(*args):
    sum = 0
    
    for n in args:
        sum = sum + n

    return sum


sum = add(3, 5)  # Call function foo with 2 arguments
print(f'Sum = {sum}')

sum = add(4, 5, 6, 7)  # Call function foo with 4 arguments
print(f'Sum = {sum}')

sum = add(1, 2, 3, 5, 6)  # Call function foo with 5 arguments
print(f'Sum = {sum}')

 

1.16 List comprehension

Initiera eller skapa en samling (collection) i en rad kod. Finns inget riktigt bra namn på svenska för list comprehension.

# Create a list with 100 items an initialize all values to 0
lst = []
for _ in range(100):
    lst.append(0)
print(lst)

# Same code with list comprehension
lst = [0 for _ in range(100)]
print(lst)
# Create a list with 100 items and initialize the values to 0, 1, 2,...,99
lst = []
for i in range(100):
    lst.append(i)
print(lst)

# Same code with list comprehension
lst = [i for i in range(100)]
print(lst)

Vill man ha alla jämna nummer upp till 100 i en lista kan man skriva

lst = []
for i in range(100):
    if i % 2 == 0:
        lst.append(i)

Eller så kan det skrivas kortare m.h.a. list comprehension som

lst = [i for i in range(100) if i % 2 == 0]

Vi har tidigare använt list comprehension för att omvandla en lista med strängar till en lista med tal.

str = input('Ange flera heltal: ')
lst = str.split()
lst = [int(n) for n in lst]

Ibland ser man kod som använder funktionen map för att åstadkomma samma sak. Men det är gammalt sätt att göra det på och numera rekommenderas att använda list comprehensions.

Se mer på: Tech With Tim

 

1.17 Lägga till element i en tuple

Som vi vet går det inte att lägga till eller ta bort element i en tuple. Det gör också att den exekveras snabbare. Men det går att göra om en tuple till lista för att kuna t.ex. lägga till element. Och sedan omvandla listan tillbaka till en tuple.

tup = (1, 2, 3)
lst = list(tup)
lst.append(4)
tup = tuple(lst)
print(tup)
Men man ska kanske fråga sig varför det ska vara en tuple om det ska gå att lägga till element.

 

1.18 Anonyma funktioner (lambda)

För att dubbla alla elementens värden i en lista kan t.ex. list comprehension användas.

# Return double of n
def double(x):
    return x * 2
  
  
# We double all numbers using list comprehension
numbers = [1, 2, 3, 4]
lst = [double(n) for n in numbers]
print(lst)

För att slippa definiera funktionen kan ett lambda-uttryck användas.

# Double all numbers using list comprehension and a lambda expression
numbers = [1, 2, 3, 4]
f = lambda x: x * 2  # Create a function with a lambda expression
lst = [f(n) for n in numbers]
print(lst)

Det går även att skriva samma kod genom att skapa en helt anonym funktion med ett lambda-uttryck.

# Double all numbers using list comprehension and an anonymous function using lambda 
numbers = [1, 2, 3, 4]
lst = [(lambda x: x * 2)(n) for n in numbers]  # Define an anonymous function with a lambda expression
print(lst)
Använd lambda uttryck som anonyma funktioner när en funktion bara behövs just där i koden.

 

1.19 Exempel på användning av tipsen

Exempel 1

# Input several numbers from one row and typecast them to integers
str = input('Skriv in tal')
lst = str.split()
for i in range(len(lst)):
    lst[i] = int(lst[i])
# Same code using chaining
lst = input('Skriv in tal').split()
for i in range(len(lst)):
    lst[i] = int(lst[i])
# Same code using list comprehension
lst = input('Skriv in tal').split()
lst = [int(n) for n in lst]
# Same code can be written as a single line statement 
lst = [int(n) for n in input('Skriv in tal: ').split()]

Exempel 2

str = input('Ange heltalen p och q i en andragradsekvation (x\u00b2 + px + q = 0): ')
lst = str.split()

# Get p and q from list and typecast them to float
p = float(lst[0])
q = float(lst[1])
# Same code using chaining
lst = input('Ange heltalen p och q i en andragradsekvation (x\u00b2 + px + q = 0): ').split()

# Get p and q from list and typecast them to float
p = float(lst[0])
q = float(lst[1])
# Same code
lst = input('Ange heltalen p och q i en andragradsekvation (x\u00b2 + px + q = 0): ').split()

# Use multiple assignment and list comprehension
p, q = [float(n) for n in lst]  # Get p and q from list and typecast them to float
# Same code can be written as a single line statement 
p, q = [float(n) for n in input('Ange heltalen p och q i en andragradsekvation (x\u00b2 + px + q = 0): ').split()]

Centralt innehåll

Fakta

Begrepp

Multiline comment: För att kommentera ett helt stycke, dvs flera rader, används ''' eller """

Chained comparison: Att jämföra en variabel mot flera värden utan logisk operator, t.ex.

10 < x < 60

Multiple assignment: Tilldela flera variabler värden i en sats, t.ex.

a, b, c = 2, 4, 7

Unpacking: Att tilldela variabler värden från samlingar, t.ex. listor

a, b, c = [3, 4, 6]

Return multiple values: En funktion kan returnera flera värden med return-satsen, t.ex.

return x, y, z

Underscore as loop iterator: Namnger en loop-variabel med understreck när den inte används i loopen, t.ex.

for _ in range(5):

Assignment in expression: Göra tilldelning i uttryck, t.ex. i villkorsuttryck, t.ex.

if (ret := foo(3)) > 10:

Ternary condition: En förkortad if-sats, t.ex.

2 if a > b else 4

Chaining: Flera anrop och/eller satser kopplas ihop till en sats, t.ex.

foo().line().my_print()

Default parameters: En funktion har en parameter med ett standarvärde som används om värde inte skickas med som argument. t.ex.

def foo(a, b, c=2):

Keyword arguments: Genom att ange namnen på parametrarna kan parameterordningen ändras, t.ex.

print_foo(1, 2, y=3)

Type hints: Att ge ledtråd om datatyper för parametrar och returvärde i funktioner, t.ex.

def foo(x: int, s: str) -> int:

Args: Anropa en funktion med variabelt antal argument, t.ex. där lst är en lista som kan ha olika antal element

ret = foo(*lst)

List comprehension: Initiera eller skapa en samling i en rad kod, t.ex.

lst = [i for i in range(100)]

Lambda: Används för att enkelt definiera funktioner och anonyma funktioner som behövs temporärt i koden

f = lambda x: x * 2

Övningar

Inlämningsuppgift

login     logout    

Exit tickets

Finn Fem Fel
Se till att du förstår koden, som använder dictionaries istället för 3 olika listor för att hantera flera konton.
Koden har inga syntaxfel och kan köras, men det finns några saker som inte stämmer med PEP 8. Finn de 5 felen och åtgärda dem.

        

PEP 8
Kolla efter följande PEP 8 regler i koden:

4 mellanslag som indentering.
Beskrivande engelska namn och snake case.
Korrekta mellanslag vid tilldelning, argument, parametrar och uttryck.
Inga parenteser i if- och while-satser.
2 tomma rader före och efter funktionsdefinitionerna.
Inga print-satser i funktionerna redraw och deposit.
Använd f-strängar vid utskrifter.
Använd en main-funktion för att undvika användning av globala variabler.
Korrekt placering, rätta antal mellanslag och stor första bokstav i kommentarer.