Väldigt bra lösning för att få in extrauppgiften i funktion inventory. Vi kan dock göra den lite bättre. Nu har vi följande kod:
def inventory(bag_list, start_str=None, stop_str=None):
"""
visar innehållet i ryggsäcken
"""
if start_str is None:
start = 0
else:
start = int(start_str)
if stop_str is None:
stop = len(bag_list)
else:
stop = int(stop_str)
temp_list = bag_list[start:stop]
print(f"ryggsäcken innehåller {len(temp_list)} saker")
print(temp_list)
for item in temp_list:
print(item)
I uppgiften står inget om vad vi måste ha som default värde på parametrarna för start och stop. Du använder None vilket är helt OK att använda och något jag föreslog på genomgången eller föreläsningen. Men med din lösning kan vi göra den bättre om vi ändrar default värdet.
Vi vill lyckas ta bort följande kod:
if start_str is None:
start = 0
else:
start = int(start_str)
Det är ingen dålig lösning i sig. Men om vi förutsätter att start_str argumentet som skickas in redan är ett heltal, det förutsätter att vi gör om till heltal i main.py, då kan vi sätta 0 som default värde istället. Då behövs inte if-satsen. start_str kommer då alltid innehålla ett heltal och det är 0 om inget argument skickas och om värdet skickas då kan vi använda det som det är.
Jag förstår om det inte har varit självklart att ni får lösen uppgiften så här, det är inte helt tydligt i uppgiften om ni får göra om värdet till heltal i main.py eller om ni måste göra det i inventory funktionen.
För stop värdet är det inte lika självklart hur vi kan bli av med if-satsen. Om vi också här förutsätter att argumentet som skickas in redan är ett heltal kan vi åtminstone förkorta den till:
if stop_str is None:
stop_str = len(bag_list)
Notera att jag inte längre använder stop som variabelnamn utan ändrar värdet i stop_str. Jag planerade först att lämna lösningen så här men för skoj skull testade jag vad som hände om man använder None som stop värde i slice. Det visade sig att None får samma effekt som att inte skriva något värde, med andra ord inkluderas alla värden fram till och med sista. T.ex. [1, 2, 3, 4][1:None] returnerar [2, 3, 4].
Med denna kunskapen kan vi ta bort if-satsen helt. Då ser funktionen ut som följande (jag bytte namn på start_str till start och stop_str till stop då de inte längre ska hålla strängar.):
def inventory(bag_list, start=0, stop=None):
"""
visar innehållet i ryggsäcken
"""
temp_list = bag_list[start:stop]
print(f"ryggsäcken innehåller {len(temp_list)} saker")
print(temp_list)
for item in temp_list:
print(item)
pick funktionen gillar jag också, det är smart att sätta i till längden av listan och på så sätt kunna använda insert för båda fallen. Men funktionen kanske är lite klurig att få en bra och snabb överblick utav. Jag vill minska antalet if-satser i koden och nu har du en if-sats som inte alltid behövs. Nu har vi funktionen:
if x is None:
i = len(bag_list)
else:
i = int(x)
if i > len(bag_list):
print(f"Error: index {i} är 'out of range'")
return bag_list
bag_list.insert(i, item)
if x is None:
print(f"{item} har lagts in i ryggsäcken")
else:
print(f"{item} har lagts in i ryggsäcken på position {i}")
return bag_list
Vi noterar att koden:
if i > len(bag_list):
print(f"Error: index {i} är 'out of range'")
return bag_list
Bara behövs om vi ska lägga in på specifikt index. Så vi börjar med att flytta in den i första else-blocket.
if x is None:
i = len(bag_list)
else:
i = int(x)
if i > len(bag_list):
print(f"Error: index {i} är 'out of range'")
return bag_list
# inte ändrat koden nedanför
bag_list.insert(i, item)
if x is None:
print(f"{item} har lagts in i ryggsäcken")
else:
print(f"{item} har lagts in i ryggsäcken på position {i}")
return bag_list
Nästa sak jag vill fokusera på är att du anropar len(bag_list) två gånger. Vid första anblick tänkte jag att vi bara ska flytta ut i = len(bag_list) ovanför if x is None: men sen insåg jag att då funkar det inte mer resten av koden och hur du använder i i insert(). Men jag föredrar att inte anropa len() två gånger och vi kan få till ett snygg flöde i koden. Då kan vi dock inte använda insert() för både fallet där användaren inte skickar med och skickar med index.
Nu kommer jag göra om koden så att den har tre tydliga flöden.
if x is not None:
i = int(x)
if i > len(bag_list):
print(f"Error: index {i} är 'out of range'")
return bag_list
bag_list.insert(i, item)
print(f"{item} har lagts in i ryggsäcken på position {i}")
return bag_list
bag_list.append(item)
print(f"{item} har lagts in i ryggsäcken")
return bag_list
Så, nu har vi tre flöden som varje slutar med en return. Vi är inte vara lika smarta med att återanvända variabler men vi kan istället ta bort lite kod och få ett tydligare flöde.
swap kommandot
Jättebra lösning, jag gillar att du skapade en ny funktion och återanvänder den. Nu har vi följande kod:
def swap(bag_list, item1, item2):
"""
byter plats på två element i ryggsäcken
"""
i1 = find_index(bag_list, item1)
i2 = find_index(bag_list, item2)
if (i1 < 0) or (i2 < 0):
return bag_list
if item1 == item2:
print(f"Error: {item1} och {item2} har samma värde")
return bag_list
temp = bag_list[i1]
bag_list[i1] = bag_list[i2]
bag_list[i2] = temp
print(f"{item1} och {item2} har nu bytt plats")
return bag_list
def find_index(bag_list, item):
"""
returnerar position för angivet item
"""
try:
return bag_list.index(item)
except ValueError:
print(f"Error: {item} finns inte i ryggsäcken")
return -1
Vi kan skriva om slutet med hjälp av tuple unpacking, vilket du inte visste om när du skrev uppgiften, men nu borde du veta vad det är.
Jättebra lösning, gör precis det den ska med minimal kod. Nu har vi följande kod:
def drop(bag, what):
"""inv drop command"""
try:
bag.remove(what)
print(f"'{what}' has been dropped.")
except ValueError:
print(f"Error: There are no '{what}' in the bagpack.")
return bag
Lab5 2.4
Här har vi uppgiften och koden. Jag pratade lite om denna uppgiften på en genomgång, i äldre python versioner kunde ni använt ",".join(tup24) för att bygga stränge. Men i någon python version tog de bort funktionaliteten att automatiskt göra om alla element till strängar innan de läggs till i strängen.
# """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
# Exercise 2.4 (1 points)
#
# Create a tuple with
#
# > (snake, 89, 9.63, bookshelf, 1)
#
# Convert it to a list and replace the second element with:
#
# > "green"
#
# Convert it back to a tuple and answer with the first three elements in a
# comma-separated string, without an ending `,`.
#
# Write your code below and put the answer into the variable ANSWER.
#
tup24 = ("snake", 89, 9.63, "bookshelf", 1)
list24 = list(tup24)
list24[1] = "green"
tup24 = tuple(list24[0:3])
str24 = ""
for i in tup24:
str24 += str(i) + ","
answer = str24[:-1]
ANSWER = answer
Med det jag skrev ovanför i åtanke är den löst på sånt sätt som vi kan förväntas i kursen med det vi har lärt er. Jag kommer bara på sätt vi kan snygga till den med saker som är lite överkurs och vi inte har lärt ut i kursen. Vi kollar hur det kan se ut. Jag kommer bara fokusera på följande del i koden, den översta är löst som man ska.
str24 = ""
for i in tup24:
str24 += str(i) + ","
ANSWER = str24[:-1]
Vi vill skapa en sträng från en lista där vi måste göra om värden till strängar först. Då kan vi använda list comprehension eller map(). Båda dem används för att itterera igenom en sekvens, köra en funktion på varje element och returnera en ny lista med det som returneras från funktionen som körs på varje lista.
map()
map() tar två argument, första är funktionen som ska köras på varje element och andra är sekvensen vi kör det på.
Marvin3
Du har väldigt bra kod, det känns som att din lösningar är genomtänkta och du anpassar koden efter lösningen du vill ha.
Jag gillar att du använder dig av if-name-main i inventory.py för att testa dina funktioner.
inv kommandot
Väldigt bra lösning för att få in extrauppgiften i funktion
inventory
. Vi kan dock göra den lite bättre. Nu har vi följande kod:I uppgiften står inget om vad vi måste ha som default värde på parametrarna för start och stop. Du använder
None
vilket är helt OK att använda och något jag föreslog på genomgången eller föreläsningen. Men med din lösning kan vi göra den bättre om vi ändrar default värdet.Vi vill lyckas ta bort följande kod:
Det är ingen dålig lösning i sig. Men om vi förutsätter att
start_str
argumentet som skickas in redan är ett heltal, det förutsätter att vi gör om till heltal i main.py, då kan vi sätta0
som default värde istället. Då behövs inte if-satsen.start_str
kommer då alltid innehålla ett heltal och det är 0 om inget argument skickas och om värdet skickas då kan vi använda det som det är. Jag förstår om det inte har varit självklart att ni får lösen uppgiften så här, det är inte helt tydligt i uppgiften om ni får göra om värdet till heltal imain.py
eller om ni måste göra det iinventory
funktionen.För stop värdet är det inte lika självklart hur vi kan bli av med if-satsen. Om vi också här förutsätter att argumentet som skickas in redan är ett heltal kan vi åtminstone förkorta den till:
Notera att jag inte längre använder
stop
som variabelnamn utan ändrar värdet istop_str
. Jag planerade först att lämna lösningen så här men för skoj skull testade jag vad som hände om man använderNone
som stop värde i slice. Det visade sig attNone
får samma effekt som att inte skriva något värde, med andra ord inkluderas alla värden fram till och med sista. T.ex.[1, 2, 3, 4][1:None]
returnerar[2, 3, 4]
.Med denna kunskapen kan vi ta bort if-satsen helt. Då ser funktionen ut som följande (jag bytte namn på
start_str
tillstart
ochstop_str
tillstop
då de inte längre ska hålla strängar.):och i main.py har vi:
pick kommandot
pick
funktionen gillar jag också, det är smart att sättai
till längden av listan och på så sätt kunna använda insert för båda fallen. Men funktionen kanske är lite klurig att få en bra och snabb överblick utav. Jag vill minska antalet if-satser i koden och nu har du en if-sats som inte alltid behövs. Nu har vi funktionen:Vi noterar att koden:
Bara behövs om vi ska lägga in på specifikt index. Så vi börjar med att flytta in den i första else-blocket.
Nästa sak jag vill fokusera på är att du anropar
len(bag_list)
två gånger. Vid första anblick tänkte jag att vi bara ska flytta uti = len(bag_list)
ovanförif x is None:
men sen insåg jag att då funkar det inte mer resten av koden och hur du använderi
iinsert()
. Men jag föredrar att inte anropalen()
två gånger och vi kan få till ett snygg flöde i koden. Då kan vi dock inte användainsert()
för både fallet där användaren inte skickar med och skickar med index.Nu kommer jag göra om koden så att den har tre tydliga flöden.
Så, nu har vi tre flöden som varje slutar med en return. Vi är inte vara lika smarta med att återanvända variabler men vi kan istället ta bort lite kod och få ett tydligare flöde.
swap kommandot
Jättebra lösning, jag gillar att du skapade en ny funktion och återanvänder den. Nu har vi följande kod:
Vi kan skriva om slutet med hjälp av tuple unpacking, vilket du inte visste om när du skrev uppgiften, men nu borde du veta vad det är.
Följande:
Blir:
drop kommandot
Jättebra lösning, gör precis det den ska med minimal kod. Nu har vi följande kod:
Lab5 2.4
Här har vi uppgiften och koden. Jag pratade lite om denna uppgiften på en genomgång, i äldre python versioner kunde ni använt
",".join(tup24)
för att bygga stränge. Men i någon python version tog de bort funktionaliteten att automatiskt göra om alla element till strängar innan de läggs till i strängen.Med det jag skrev ovanför i åtanke är den löst på sånt sätt som vi kan förväntas i kursen med det vi har lärt er. Jag kommer bara på sätt vi kan snygga till den med saker som är lite överkurs och vi inte har lärt ut i kursen. Vi kollar hur det kan se ut. Jag kommer bara fokusera på följande del i koden, den översta är löst som man ska.
Vi vill skapa en sträng från en lista där vi måste göra om värden till strängar först. Då kan vi använda list comprehension eller map(). Båda dem används för att itterera igenom en sekvens, köra en funktion på varje element och returnera en ny lista med det som returneras från funktionen som körs på varje lista.
map()
map()
tar två argument, första är funktionen som ska köras på varje element och andra är sekvensen vi kör det på.Vi använder map för att göra om alla element till strängar och returnerar det som en ny lista. Vi skickar in den som argument till
join()
funktionen.List comprehension
List comprehension är lite mer dynamisk och kan användas till mer än map. Det är en konstruktion och inte en funktion. Det påminner om en for-loop.
Bild på strukturen
I vår list comprehension loopar igenom vår skevens med en for loop och anropar
str()
på varje element. Sen funkar det likadant som medmap()
.Slutsats
Vilken lösning är bäst? Jag vet inte, list comprehension är väl mer "pythonic". Om ni är intresserade kan ni läsa mer om list comprehension vs map.