l = ["en", "lista", "med", "värden"]
print(f"första värdet: {l[0]}")
första värdet: en
=
efter ett uttryck för att få dess värdes = "batteri"
print(f"{s=}")
s='batteri'
def hejsan():
print("Hejsan")
hejsan()
hejsan
def print_hello():
print("Hello World!")
bacon = print_hello
bacon()
Hello World!
print()
, open()
self
i metoddefinitioner) kan bindas mha nyckelordsargument.def happy_anniversary(name, occasion="födelsedagen", num=1):
print(f"Grattis på {occasion}, {name}!")
print(f"Tänk att du firat detta {num} gånger nu!")
happy_anniversary("Ragiähl")
Grattis på födelsedagen, Ragiähl! Tänk att du firat detta 1 gånger nu!
happy_anniversary("Önde", "namnsdagen, eller inte", 0)
Grattis på namnsdagen, eller inte, Önde! Tänk att du firat detta 0 gånger nu!
happy_anniversary(num=42, name="Gjohl",)
Grattis på födelsedagen, Gjohl! Tänk att du firat detta 42 gånger nu!
*args
: *args
men man ser varianter som *objects
**kwargs
: def add(term1, term2):
return term1 + term2
def multiply(factor1, factor2):
return factor1 * factor2
def aggregate(*args, function=add):
result = args[0]
for arg in args[1:]:
result = function(result, arg)
return result
aggregate(1,2,3,4,5, function=multiply)
120
def print_pairs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_pairs(name="Norville Rogers", hometown="Coolsville, OH", company="Mystery, Inc.")
print_pairs(course_name="Graph Theory", exam1="0 points", exam2="3 points", grade="Let's never talk about this again.")
name: Norville Rogers hometown: Coolsville, OH company: Mystery, Inc. course_name: Graph Theory exam1: 0 points exam2: 3 points grade: Let's never talk about this again.
def add(term1, term2):
return term1 + term2
def aggregate(*args, fun=add):
result = args[0]
for arg in args[1:]:
result = fun(result, arg)
return result
def multiply(factor1, factor2):
return factor1 * factor2
aggregate(1,2,3,4,5, fun=multiply)
120
def happy_anniversary(name, occasion="födelsedagen", num=1):
print(f"Grattis på {occasion}, {name}!")
print(f"Tänk att du firat detta {num} gånger nu!")
happy_anniversary("Ragiähl")
Grattis på födelsedagen, Ragiähl! Tänk att du firat detta 1 gånger nu!
happy_anniversary("Önde", "namnsdagen, eller inte", 0)
Grattis på namnsdagen, eller inte, Önde! Tänk att du firat detta 0 gånger nu!
print
¶print
¶print("We", "can", "actually", "add", "however", "many", "arguments", "we", "want")
We can actually add however many arguments we want
print("We can", "also change", "the separator", sep="\n")
We can also change the separator
print("or the", end=' ')
print("end")
or the end
with open("printtest.txt", 'w') as outfile:
print("Or print to a file rather than stdout!", file=outfile)
Mellan en (oftast mänsklig) användare och någon form av system, t.ex.
Bestämma layout för widgets i ett GUI.
Inte att ge en introduktion till hur moderna GUI-ramverk fungerar (mer om dessa i kurser senare i programmet).
# Importera tkinter
import tkinter as tk
# Ett rot-fönster
root = tk.Tk()
# Widgets läggs in i rot-fönstret
button = tk.Button(root, text="Press me!")
# Widgets layoutas
button.pack()
# Huvudloopen startas
root.mainloop()
Widget | Description |
---|---|
Button | A simple button, used to execute a command or other operation. |
Canvas | Structured graphics. This widget can be used to draw graphs and plots, create graphics editors, and to implement custom widgets. |
Checkbutton | Represents a variable that can have two distinct values. Clicking the button toggles between the values. |
Entry | A text entry field. |
Frame | A container widget. The frame can have a border and a background, and is used to group other widgets when creating an application or dialog layout. |
Label | Displays a text or an image. |
Listbox | Displays a list of alternatives. The listbox can be configured to get radiobutton or checklist behavior. |
Widget | Description |
---|---|
Menu | A menu pane. Used to implement pulldown and popup menus. |
Menubutton | A menubutton. Used to implement pulldown menus. |
Message | Display a text. Similar to the label widget, but can automatically wrap text to a given width or aspect ratio. |
Radiobutton | Represents one value of a variable that can have one of many values. Clicking the button sets the variable to that value, and clears all other radiobuttons associated with the same variable. |
Scale | Allows you to set a numerical value by dragging a "slider". |
Scrollbar | Standard scrollbars for use with canvas, entry, listbox, and text widgets. |
Text | Formatted text display. Allows you to display and edit text with various styles and attributes. Also supports embedded images and windows. |
Toplevel | A container widget displayed as a separate, top-level window. |
# importera tkinter-modulen
from tkinter import *
# skapa ett Tk-fönster
window = Tk()
# starta GUI-loopen
mainloop()
Huvudfönstret i Tkinter är ett objekt av typen (klassen) Tk
. För att utritning av fönster etc. ska
göras, måste man starta GUI:ts huvudloop: mainloop()
(funktionen ligger i modulen tkinter
)
# windows.py
from tkinter import *
# Skapa det första fönstret
root = Tk()
# Skapa det andra fönstret
top = Toplevel()
# Starta Tk-loopen
root.mainloop()
För att skapa fler än ett fönster utöver det första används klassen Toplevel
.
# utan att spara referens
Widget(parent, attribute1=v1, attribute2=v2, ...)
# med referensen sparad
w = Widget(parent, attribute1=v1, attribute2=v2, ...)
När man skapar en widget, skapar en instans av en widgetklass, måste man ange dess förälder.
Föräldern (parent
) är ett fönster eller en widget som kan agera "behållare".
Button
¶# importera tkinter-modulen
import tkinter as tk
# skapa ett rot-fönster
root = tk.Tk()
button = tk.Button(root, text="Press me!")
button.pack()
# starta GUI-loopen
root.mainloop()
button = tk.Button(root, text="OK", command=do_this)
do_this
är ett funktionsobjekt.# importera tkinter-modulen
import tkinter as tk
def callback():
"""Print a set string when called."""
print("Something happened!")
# skapa ett Tk-fönster
root = tk.Tk()
button = tk.Button(root, text="Press Me!", command=callback)
button.pack()
# starta GUI-loopen
root.mainloop()
Something happened!
"<Button-1>"
som betyder att musknapp 1 har tryckts ner.bind()
-metoden:def key_handler(event):
print("A key was pressed")
Event
som parameterEvent
-objekt kan man läsa av diverse information. Se referensmaterialet."<Enter>"
när musen förs in i över en widget"<Leave>"
när musen lämnar en widget"<KeyPress>"
när en tangent trycks ner"<KeyRelease>"
när en tangent åker upp igen"<Button-1>"
när musknapp 1 trycks"<Button-2>"
när musknapp 2 trycksimport tkinter as tkx
def callback():
print("Something happened!", end=' ')
def over_me(event):
print("You are over me!", end=' ')
def left_me(event):
print("You left me!", end=' ')
# skapa ett Tk-fönster och knapp
root = tk.Tk()
button = tk.Button(root, text="Press Me!", command=callback)
# bind funktioner till Enter/Leave-händelserna
button.bind("<Enter>", over_me)
button.bind("<Leave>", left_me)
button.pack()
# starta GUI-loopen
root.mainloop()
You are over me! You left me! You are over me! You left me! You are over me! You left me! You are over me! You left me! You are over me! Something happened! Something happened! Something happened! You left me!
Label
¶Label
-instans används som etiketter i ett GUI.Entry
¶Entry
är ett textfält som har en rad.Entry
genom att anropa på dess metod get()
.insert()
och delete()
.insert()
behöver ett start-index och en sträng, t.ex. entry1.insert(0, "hej")
.delete()
behöver ett start-index.import tkinter as tk
# skapa och placera en frame i ett fönster
root = tk.Tk()
def key(event):
"""Skriv ut debugutskrifter för textfält."""
if event.widget == entry1:
print(entry1.get())
if event.widget == entry2:
print("Entry 2 changed")
# Entry 1
entry1 = tk.Entry(root)
entry1.bind("<KeyRelease>", key)
entry1.pack()
# Entry 2
entry2 = tk.Entry(root)
entry2.bind("<KeyRelease>", key)
entry2.pack()
root.mainloop()
Frame
¶Frame
-objekt är att gruppera widgets.Frame
. Sen lägger man till denna till ett fönster.pack
grid
place
grid
.grid
¶(I både Android och iOS kan man ha "widgets" på sin startskärm, t.ex. klocka, väder, nyhetsfeed, aktiekurser, mediaspelare, etc. Dessa brukar man oftast kunna placera ut enligt samma grid-princip som Tkinters `grid`-metod använder.)
grid
forts.¶grid
i referensmaterialet# grid.py
import tkinter as tk
# Framen läggs automatisk in i en tk.Tk()
frame = tk.Frame()
# placera frame i fönstret med hjälp av pack()
frame.pack()
# titel-label
title_label = tk.Label(frame, text="The best game character ever",
background="red")
title_label.grid(row=0, column=0, columnspan=2, sticky=tk.E+tk.W+tk.N+tk.S)
# namn-label
name_label = tk.Label(frame, text="Name")
name_label.grid(row=1, column=0, sticky=tk.NW)
# name-textfält
name_entry = tk.Entry(frame)
name_entry.grid(row=1, column=1, sticky=tk.NW)
# game-label
game_label = tk.Label(frame, text="Game")
game_label.grid(row=2, column=0, sticky=tk.NW)
# name-textfält
game_entry = tk.Entry(frame)
game_entry.grid(row=2, column=1, sticky=tk.NW)
# knapp
button = tk.Button(frame, text="Ok")
button.grid(row=3, column=1, sticky=tk.SE)
frame.mainloop()
StringVar
som tar hand om strängarIntVar
som tar hand om int:ars = tk.StringVar()
s.set("hej")
print(s.get())
# radio.py
import tkinter as tk
root = tk.Tk()
def radio():
"""Skriv ut värdet hos radio-knappen."""
print(radio_value.get())
# Tk-variabel att lagra radioknapp-gruppens värde i
radio_value = tk.StringVar()
radio_value.set("inget valt")
# knapp 1
radio_button1 = tk.Radiobutton(root, text="Hejsan", variable=radio_value,
value="hejsan", command=radio)
radio_button1.pack()
# knapp 2
radio_button2 = tk.Radiobutton(root, text="Hoppsan", variable=radio_value,
value="hoppsan", command=radio)
radio_button2.pack()
# knapp 3
radio_button3 = tk.Radiobutton(root, text="Svejsan", variable=radio_value,
value="svejsan", command=radio)
radio_button3.pack()
root.mainloop()
hejsan svejsan hoppsan svejsan
IntVar
) som man kopplar till knappen.def hello(name, index, mode):
print(v.get())
v = tk.StringVar()
v.set("eggs")
v.trace('w', hello)
v.set("bacon")
# checkbox.py
import tkinter as tk
root = tk.Tk()
def check_changed(name, index, mode):
"""Skriv ut debug-utskrifter för checkboxar."""
# name är namnet på den variabeln som triggade check_changed
# i detta exempel finns två kandidater, check_val1 som har
# namnet "check1" och check_val2 som har namnet "check2".
if name == "check1":
print("check 1: " + str(check_val1.get()), end=' | ')
elif name == "check2":
print("check 2: " + str(check_val2.get()), end=' | ')
# skapa en instans av IntVar som får namnet "check1"
check_val1 = tk.IntVar(name="check1")
# när värdet på check_val1 ändras, kör funktionen check_changed()
check_val1.trace('w', check_changed)
# skapa en instans av IntVar som får namnet "check2"
check_val2 = tk.IntVar(name="check2")
# när värdet på check_val2 ändras, kör funktionen check_changed()
check_val2.trace('w', check_changed)
# skapa två checkbuttons, koppla ihop dem med var sin variabel
checkbutton1 = tk.Checkbutton(root, variable=check_val1,
text="box of check I am")
checkbutton2 = tk.Checkbutton(root, variable=check_val2,
text="box of check I am too")
# lägg till knapparna till layouten
checkbutton1.pack()
checkbutton2.pack()
root.mainloop()
check 1: 1 | check 2: 1 | check 2: 0 | check 2: 1 | check 1: 0 | check 2: 0 |
StringVar
# optionmenu.py
import tkinter as tk
root = tk.Tk()
var = tk.StringVar(root)
var.set("one") # initial value
option = tk.OptionMenu(root, var, "one", "two", "three", "four")
option.pack()
def ok():
print("value is", var.get(), end=' | ')
button = tk.Button(root, text="OK", command=ok)
button.pack()
tk.mainloop()
value is one value is three value is four
if __name__ == "__main__":
# kod här
Skriv ut variabler, delresultat, resultat, etc. (spårutskrifter)
def my_clever_function(an_argument, another_argument):
print("\n--------------------\n")
print("In my_clever_function:")
print(f"{an_argument=}")
print(f"{another_argument=}")
Testa med assertions
assert sanningsuttryck
assert my_function(5) > 100
assert my_sorted([5, 2, 6]) == [2, 5, 6]
count_integers(value_list)
som returnerar antalet heltal i en lista (argumentet value_list
)def count_integers(value_list):
num_ints = 0
for value in value_list:
if type(value) == int:
num_ints += 1
return num_ints
print(f"{count_integers([1, 2, 3, 4])=}")
assert count_integers([1, 2, 3, 4]) == 4
assert count_integers([1, 2, 3, 4]) == 3
count_integers([1, 2, 3, 4])=4
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) Cell In[4], line 10 8 print(f"{count_integers([1, 2, 3, 4])=}") 9 assert count_integers([1, 2, 3, 4]) == 4 ---> 10 assert count_integers([1, 2, 3, 4]) == 3 AssertionError:
# localglobal.py
def print_global_name():
"""Skriv ut globala variabeln name."""
global name
print(f"global name: {name}")
def change_and_print_local_name(name):
"""Ändra och skriv utlokala variabeln name."""
# alla variabler i en funktion är lokala om inte annat anges
secret = "When this function returns, I am gone."
name = name * 2
print(f"changed local name: {name}")
def change_and_print_global_name():
"""Ändra och skriv ut globala variabeln name."""
global name
name = name * 2
print(f"changed global name: {name}")
name = "Ada"
print_global_name()
change_and_print_local_name(name)
print_global_name()
change_and_print_global_name()
print_global_name()
global name: Ada changed local name: AdaAda global name: Ada changed global name: AdaAda global name: AdaAda
# localvars.py
def find_min_and_max(values):
min_val = None
max_val = None
for value in values:
if type(value) != int:
continue
if min_val is None and max_val is None:
min_val = value
max_val = value
continue
if value > max_val:
max_val = value
if value < min_val:
min_val = value
print(f"min: {min_val}, max: {max_val}")
my_values1 = ["a", 10, 90, -100, 80, 900, "nehepp"]
my_values2 = ["a", 1, 9, -10, 8, 90, "jahapp"]
find_min_and_max(my_values1)
find_min_and_max(my_values2)
# Här går koden sönder, varför?
print(max_val)
print(min_val)
min: -100, max: 900 min: -10, max: 90
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[6], line 27 24 find_min_and_max(my_values2) 26 # Här går koden sönder, varför? ---> 27 print(max_val) 28 print(min_val) NameError: name 'max_val' is not defined
# globalvars.py
min_val = None
max_val = None
def find_min_and_max(values):
global min_val, max_val
for value in values:
if type(value) != int:
continue
# om vi inte har något min/max än
if min_val is None and max_val is None:
min_val = value
max_val = value
continue
# uppdatera när vi hittar nytt min/max
if value > max_val:
max_val = value
if value < min_val:
min_val = value
print(f"min: {min_val}, max: {max_val}")
my_values1 = ["a", 10, 90, -100, 80, 900, "nehepp"]
my_values2 = ["a", 1, 9, -10, 8, 90, "jahapp"]
find_min_and_max(my_values1)
print(max_val)
print(min_val)
# varför blir det fel här? Minsta heltalet är ju -10 i my_values2
find_min_and_max(my_values2)
print(max_val)
print(min_val)
min: -100, max: 900 900 -100 min: -100, max: 900 900 -100
# insertionsort original
def insertionsort(list_to_sort,order):
for i in range(1,len(list_to_sort)):
currentvalue = list_to_sort[i]
pos = i
if order == "ascending":
while (pos >= 1 and list_to_sort[pos - 1] > currentvalue):
list_to_sort[pos]=list_to_sort[pos - 1]
pos = pos - 1
elif order == "descending":
while (pos >= 1 and list_to_sort[pos - 1] < currentvalue):
list_to_sort[pos]=list_to_sort[pos - 1]
pos = pos - 1
list_to_sort[pos]=currentvalue
alist = [54,26,93,17,77,31,44,55,20]
insertionsort(alist, "ascending")
print("Ascending", alist)
alist = [54,26,93,17,77,31,44,55,20]
insertionsort(alist, "descending")
print("Descending", alist)
Ascending [17, 20, 26, 31, 44, 54, 55, 77, 93] Descending [93, 77, 55, 54, 44, 31, 26, 20, 17]
if order == "ascending":
while (pos >= 1 and list_to_sort[pos - 1] > currentvalue):
list_to_sort[pos]=list_to_sort[pos - 1]
pos = pos - 1
elif order == "descending":
while (pos >= 1 and list_to_sort[pos - 1] < currentvalue):
list_to_sort[pos]=list_to_sort[pos - 1]
pos = pos - 1
# insertionsort utbruten
def insertionsort(alist, order):
for i in range(1, len(alist)):
currentvalue = alist[i]
pos = i
while (pos >= 1 and prev_val_should_move(alist[pos-1],
currentvalue, order)):
alist[pos] = alist[pos-1]
pos -= 1
alist[pos] = currentvalue
def prev_val_should_move(value1, value2, order):
if order == "ascending":
return value1 > value2
elif order == "descending":
return value1 < value2
alist = [54,26,93,17,77,31,44,55,20]
insertionsort(alist, "descending")
print("Desc:", alist)
insertionsort(alist, "ascending")
print("Asc:", alist)
Desc: [93, 77, 55, 54, 44, 31, 26, 20, 17] Asc: [17, 20, 26, 31, 44, 54, 55, 77, 93]
my_length_fun = len
another_print = print
another_print(my_length_fun(["a","short","list"]))
3
# insertionsort som högre ordningens funktion
def insertionsort(alist, order_fn):
for i in range(1, len(alist)):
currentvalue = alist[i]
pos = i
# argumentet order_fn till funktionen är den funktion som
# ska användas för jämförelsen
while (pos >= 1 and order_fn(alist[pos-1], currentvalue)):
alist[pos]=alist[pos-1]
pos -= 1
alist[pos]=currentvalue
def asc_order(value1, value2):
return value1 > value2
def desc_order(value1, value2):
return value1 < value2
alist = [54,26,93,17,77,31,44,55,20]
insertionsort(alist, desc_order)
print("Desc:", alist)
insertionsort(alist, asc_order)
print("Asc:", alist)
Desc: [93, 77, 55, 54, 44, 31, 26, 20, 17] Asc: [17, 20, 26, 31, 44, 54, 55, 77, 93]
klassnamn()
och vi behöver inte spara det skapade objektet i en variabel för att kunna använda det.sorted(list())
print(str(1))
def
måste vi ge ett namn.lambda arg1, arg2, ... argn: <uttryck_att_returnera>
lambda x: x[0]
sort()
, max()
, min()
filter()
lambda x, y: x > y
# insertionsort som högre ordningens funktion med lambda-argument
def insertionsort(alist, order_fn):
for i in range(1, len(alist)):
currentvalue = alist[i]
pos = i
# argumentet order_fn till funktionen är den funktion som
# ska användas för jämförelsen
while (pos >= 1 and order_fn(alist[pos-1], currentvalue)):
alist[pos]=alist[pos-1]
pos -= 1
alist[pos]=currentvalue
alist = [54,26,93,17,77,31,44,55,20]
insertionsort(alist, lambda x, y: x < y)
print("Desc:", alist)
insertionsort(alist, lambda x, y: x > y)
print("Asc:", alist)
Desc: [93, 77, 55, 54, 44, 31, 26, 20, 17] Asc: [17, 20, 26, 31, 44, 54, 55, 77, 93]
# pythons inbyggda funktion sorted() kan ta emot nyckelordsargumentet key som är en
# funktion som den ska använda för att plocka fram värdet som något ska sorteras efter.
# säg att vi har en lista av ord-ordfrekvenspar
wordlist = [["ord1", 10], ["ord2", 32], ["ord3", 5]]
# vi skriver en funktion som tar ordfrekvenspar och returnerar dess frekvens
def get_freq(word_and_freq):
return word_and_freq[1]
# vi kan nu skicka med funktionen till sort för att sortera listan efter frekvens
print(f"{sorted(wordlist, key=get_freq)=}")
# istället för att definiera en vanlig namngiven funktion, kan vi använda ett
# lambdauttryck (som evalueras till ett funktionsobjekt)
print(f"{sorted(wordlist, key=lambda word_and_freq: word_and_freq[1])=}")
sorted(wordlist, key=get_freq)=[['ord3', 5], ['ord1', 10], ['ord2', 32]] sorted(wordlist, key=lambda word_and_freq: word_and_freq[1])=[['ord3', 5], ['ord1', 10], ['ord2', 32]]
min()
, max()
¶max()
och min()
kan ta in en funktion som används för att ta fram det värde som ska jämföras via nyckelordsargumentet key
:max(values, key=func)
min(values, key=func)
wordlist = [["ord1", 10], ["ord2", 32], ["ord3", 5]]
# mest frekventa ordet, funktionsargumentet ska returnera det värde
# som max() ska använda för att jämföra element med varandra
print(f"max_word = {max(wordlist, key=lambda wf: wf[1])}")
# minst frekventa ordet, samma som max()
print(f"min_word = {min(wordlist, key=lambda wf: wf[1])}")
# kom ihåg, om vi itererar över ett dictionary är det nycklarna vi
# itererar över
contestants = {"ada": 1, "boris": -10, "cissi": 5, "doris": 3}
print(f"winner = {max(contestants, key=lambda name: contestants[name])}")
max_word = ['ord2', 32] min_word = ['ord3', 5] winner = cissi
filter()
¶True
förwordlist = [["apa", 10], ["fisk", 32], ["alligator", 5] ]
# ta fram alla ord i wordlist som börjar på "a"
# första argumentet är en funktion som returnerar True för de element som ska behållas
print(f"a_list = {filter(lambda wf: wf[0].startswith('a'), wordlist)}")
# ta fram alla ord i words vars sista tecken är char
words = ["bror", "bok", "bar", "barberare"]
char = "r"
print(f"ends_with_char = {list(filter(lambda word: word[-1] == char, words))}")
# titta bara på rader som inte har "N/A" som värde på index 2
for row in filter(lambda r: r[2] != "N/A", csv_data):
pass # gör grejer
a_list = <filter object at 0x000001CE596351B0> ends_with_char = ['bror', 'bar']
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[51], line 12 9 print(f"ends_with_char = {list(filter(lambda word: word[-1] == char, words))}") 11 # titta bara på rader som inte har "N/A" som värde på index 2 ---> 12 for row in filter(lambda r: r[2] != "N/A", csv_data): 13 pass NameError: name 'csv_data' is not defined