Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  73 4836
Heisan!

I forbindelse med noen nye fag på skolen må jeg lære meg å bruke Python som språk og regneverktøy. Det jeg skal kunne er veldig elementært, men jeg har aldri interessert meg for programmering og er helt blank.

Jeg har kommet et stykke på vei ved å bruke guider på codeacademy, men rett som det er står jeg fast med det ting som skulle vært kjempelett.

Det blir nok en del frustrasjon fremover og jeg lager denne tråden for å samle opp alle mine spørsmål som vitner om udugelighet
Jeg vil tro at alle som har vært borti dette kan svare på spørsmålene mine.

Nå sitter jeg fast med if, else og elif statements som ikke virker som jeg ønsker. Kan noen påpeke feilen min?

Kode

age = raw_input("Hvor gammel er du?")

if age >= 18:
    print "Du er myndig"
else:
    print "Du er ikke myndig"
I følge koden min er alle myndige uavhengig av input
Sist endret av Pope; 24. august 2017 kl. 12:02.
Hva slags datatype er age når du sammenligner i if'n ?
Jeg tror feilen kommer fra den første linjen. Det du skriver som raw_input(på command line) vil bli lagret som en string, ikke et integer. En string er, så vidt jeg vet, alltid større enn en int:

eksempel:

>>> str(2) > 2 True

For å fikse dette kan du for eksempel skrive første linje slik:

age = int(raw_input("Hvor gammel er du?"))

På den måten tvinger du python til å lagre "age" som en integer, og da vil det funke
Kan jeg spørre hvorfor du lærer Python 2 fremfor 3?
LEIK
Pope's Avatar
Trådstarter
Sitat av thedonkeybong Vis innlegg
Kan jeg spørre hvorfor du lærer Python 2 fremfor 3?
Vis hele sitatet...
Det kan du absolutt gjøre. Jeg har en foreleser som har laget skript i python 2 som ikke tar seg tid til å gjøre skriptene kompatible med python 3. Derfor.

Er det stor forskjell på 2 og 3? Hva er i såfall annerledes?

Nytt problem:

Jeg holder på med funksjoner og jeg tror jeg klarer å kalle på funksjonen.
Men hvordan printer jeg ut total sum til slutt?

Jeg antar at jeg har problemer fordi jeg forsøker å kalle på en variabel som kun finnes i den lukkede funksjonen.

Kode

def hotel_cost(netter):
  total = 140 * netter
  	return total
  
hotel_cost(raw_input("Hvor mange netter? "))

print total
edit:
Fant løsningen selv.

Kode

def hotel_cost(netter):
  total = 140 * netter
  return total
  
total = hotel_cost(int(raw_input("Hvor mange netter? ")))

print total
Er dette en "ryddig måte å gjøre det på?
Sist endret av Pope; 24. august 2017 kl. 15:52. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
Gyps bengalensis
vidarlo's Avatar
Administrator
Sitat av Pope Vis innlegg
edit:
Fant løsningen selv.

Kode

def hotel_cost(netter):
  total = 140 * netter
  return total
  
total = hotel_cost(int(raw_input("Hvor mange netter? ")))

print total
Er dette en "ryddig måte å gjøre det på?
Vis hele sitatet...
Det er den ryddige måten å gjere det på. Variabler deklarert i ein funksjon er lokale, og finst ikkje utanfor den funksjonen. Det står garantert i boka.

Return er retur-verdien til ein funksjon - og her tilordner du den til ein verdi. Du kunne like gjerne køyrt print hotel_cost(blablabla), eller tilordna den til variabelen foo.
Sitat av Pope Vis innlegg

Kode

def hotel_cost(netter):
  total = 140 * netter
  return total
  
total = hotel_cost(int(raw_input("Hvor mange netter? ")))

print total
Er dette en "ryddig måte å gjøre det på?
Vis hele sitatet...
Nei, du burde separere input så det kommer klart frem i egen variabel og fjerne litt unødvendige ting, her har du et fort og gæli forslag:

Kode

def hotel_cost(netter):
  return 140 * netter

netter = int(raw_input("hvor mange netter?"))  

print hotel_cost(netter)
PS: ja, jeg er fult klar over at dette ikke er absolutt beste måten å løse det på, men gitt at noe særlig mer konvensjonsmas kan bli rotete og uforståelig når man lærer å kode, skriver jeg det sånn.
LEIK
Pope's Avatar
Trådstarter
Takk vidarlo og Xasma

Tingen er at jeg har et fag som egentlig krever at jeg har hatt et programmeringsfag tidligere, hvilket jeg ikke har. Litt rotete opplegg fra skolens side, men resultatet er uansett at jeg må lære meg dette på egenhånd for å kunne henge med i det nye faget mitt.
Dette er årsaken til at jeg ikke har noen bestemt bok å slå opp i, vidarlo

En annen ting jeg synes er litt funky er å kalle på funksjoner med flere variabler:

Jeg har tre ulike funksjoner, hver av dem avhengig av hver sin variabel.
Deretter lager jeg en ny funksjon som skal kalle på de tre andre funksjonene og summere totalprisen.

Kode

def trip_cost(city, days):
  return hotel_cost(days) + plane_ride_cost(city) + rental_car_cost(days)
Guiden sier at det er helt greit å bruke days to ganger, selv om de lukkede funksjonene er avhengig av variabler kalt days, nights og city.

Det kan jeg godta, men hvordan vet funksjonen som egentlig er avhengig av nights at den skal bruke days- og ikke city-verdien?
Sist endret av Pope; 24. august 2017 kl. 16:48.
Er det stor forskjell på 2 og 3? Hva er i såfall annerledes?
Vis hele sitatet...
Det har skjedd en god del,som ny bruker er det helt klart en fordel og begynne med Python 3.6.

Er jo greit og skrive om,kan også bruke 2to3 som kommer med Python under Tools/Scripts.
Ser sånn ut,her også med f-string som er nytt for 3.6.

Kode

def hotel_cost(netter):
    total = 140 * netter
    return total

days = int(input("Hvor mange netter? "))
print(f'{days} netter har en en pris på {hotel_cost(days)}.-')
Output:

Kode

Hvor mange netter? 5
5 netter har en en pris på 700.-
LEIK
Pope's Avatar
Trådstarter
Stryk det siste spørsmålet mitt. Jeg ser jo at jeg selv bestemmer hvilken variabel jeg bruker når jeg kaller på de ulike funksjonene.

Er overgangen fra 2-3 vanskelig om man lærer seg 2 da? Virker litt meningsløst å bruke tid på dette om jeg må lære mye på nytt når jeg skal bruke 3.
Gyps bengalensis
vidarlo's Avatar
Administrator
Sitat av Pope Vis innlegg
Er overgangen fra 2-3 vanskelig om man lærer seg 2 da? Virker litt meningsløst å bruke tid på dette om jeg må lære mye på nytt når jeg skal bruke 3.
Vis hele sitatet...
Kan du programmering handler nye språk seg om å lære syntax. Ein dag gjer mykje.

Viare er ikkje python 2 på dødsleiet akkurat. 3 er nok på frammarsj, men det e rnok en del år til 2 er dødt.
Ting blir fremdeles skrevet og vedlikeholdt for både Python 2.4, 2.5, 2.6 og 2.7, alt avhengig av hvor gammel installasjon man har (på en produksjonsserver er det ikke helt uhørt at man er begrenset til 2.4 eller 2.5). Python 3 er fint og flott og har mange fordeler, men fremdeles er det noen moduler jeg bruker aktivt som ennå ikke er portet fra 2 til 3, så da er jeg stuck med 2.7, ihvertfall i overskuelig fremtid.
Sitat av Pope Vis innlegg
Er overgangen fra 2-3 vanskelig om man lærer seg 2 da? Virker litt meningsløst å bruke tid på dette om jeg må lære mye på nytt når jeg skal bruke 3.
Vis hele sitatet...
Overgangen er nok grei,
men som ny bruker er det best og bli vant til Python 3.
Det går fint og ha Python 2 og Python 3 installert samtidig.

Som nevnt kan bruke 2to3 for og gjøre Python 2 til Python 3.

Kode

C:\Python36\Tools\scripts
λ 2to3 -w pope.py
Etter denne ha kjørt ser det sånn ut.

Kode

def hotel_cost(netter):
    total = 140 * netter
    return total

total = hotel_cost(int(input("Hvor mange netter? ")))
print(total)
Som du ser har print() blitt en funksjon og raw_input() har blitt fjernet,
kun input() i Python 3.
Sist endret av snippsat; 24. august 2017 kl. 17:44.
▼ ... over en uke senere ... ▼
LEIK
Pope's Avatar
Trådstarter
Ny liten nøtt. Mulig dette blir et mer diffust spørsmål, men vi prøver.
Jeg bruker disse linjene:

Kode

KS = np.zeros((16,16),dtype=float)
KS = add2stiffness(K1,local2global1,KS)    
KS = add2stiffness(K2,local2global2,KS)    
KS = add2stiffness(K3,local2global3,KS)
KS = add2stiffness(K4,local2global4,KS)    
KS = add2stiffness(K5,local2global5,KS)    
KS = add2stiffness(K6,local2global6,KS)
til å kalle på følgende funksjon: (Vet jeg kan bruke for-løkke, men er ikke det som er problemet her).

Kode

def add2stiffness(ke,local2global,KS):
    [nrow,ncol] = shape(ke) #linjer og kolonner i ke
    for i in range(nrow): 
        ig = local2global[i]-1
        for j in range(ncol):
            jg = local2global[j]-1
   
            KS[ig,jg] = KS[ig,jg] + ke[i,j]
   
    return ks
Når jeg kjører koden får jeg følgende feilmelding:
IndexError: index 6 is out of bounds for axis 1 with size 6

Kodesnuttene sier vel ikke så mye uten at dere vet hva variablene er, men variablene som sendes til funksjonen er altså matriser.

Hva kan en slik feilmelding skyldes? Feil matrisedimensjoner?
KS[ig,jg] = KS[ig,jg] + ke[i,j] skal være KS[ig][jg] = KS[ig][jg] + ke[i][j]. Eneste jeg klarer å se, uten at jeg vet mer om hvordan matrisene ser ut.

EDIT: return ks betyr heller ingenting ut fra hva jeg ser. "ks" er ikke definert noe som helst sted.
Sist endret av Likyhane; 7. september 2017 kl. 11:14.
LEIK
Pope's Avatar
Trådstarter
Det du nevner først har ingen betydning, så vidt jeg vet. Men feilen lå nok i returnen ja
Vet ikke om det virker enda, for resten av skriptet er veldig ufullstendig, men jeg fortsetter.
I python og de fleste andre programmeringspåk så starter indeksering fra null, mens det i mattematikken starter fra 1. Dvs, hvis du skal ha f.eks i,j=6,6 i ett matrise så blir dette i python [5,5].

IndexError: index 6 is out of bounds for axis 1 with size 6
Her har du et array med 6 elementer. Siden indekseringen starter fra 0 vil det siste elementet være indeksert som 5. element 6 er da ikke i arrayet.
▼ ... noen måneder senere ... ▼
LEIK
Pope's Avatar
Trådstarter
På'n igjen :P
Jeg haltet meg igjennom det forrige kurset og tar nå et annet kurs som i grunnen er mye mer grunnleggende. Nå bruker jeg Python 3.6.

Jeg skal lage et veldig enkelt script som kan konvertere lengder.

Kode

m = input("Hvor mange meter?")
inch = 39.3700787*m
feet = 12*inch
yard = 3*feet
mile = 1760*yard
print()
print ("{0} meters equals: {1} inch(es), {2} feet, {3} yard(s), {4} mile(s)".format(m, inch, feet, yard, mile))
Jeg får feilmeldingen:TypeError: can't multiply sequence by non-int of type 'float'

Dette tolker jeg som at Python liker ikke at jeg taster inn integer for meter og multipliserer med flyttall ved inch-konverteringen.

Om jeg gjør om 0.0264 til et integer og kjører scriptet så krasjer python fullstendig. Hva er galt?

edit: Endret inch-konvertering
edit2: Hehe, alle konverteringene er feil, men programmet skulle likevel ha virket?

Har oppdaget at feilen som gjør at det krasjer må ligge i input(). Hvorfor er dette et problem?
Sist endret av Pope; 2. februar 2018 kl. 13:59. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
Kjedelig Streiting™
Realist1's Avatar
Er det linje 2 du får feilmelding på? Jeg har ikke PC for hånden, så får ikke testet, men min første tanke er at input-funksjonen lagrer input som streng. Prøv m = float(input('...'))
LEIK
Pope's Avatar
Trådstarter
Dette blir rotete, men her er hvertfall et oppdatert skript som i det minste konverterer riktig vei:

Kode

m = 100*input("Hvor mange meter?")
inch = m/2.54
feet = inch/12
yard = feet/3
mile = yard/1760
m=m/100
print()
print ("{0} meters equals: {1} inch(es), {2} feet, {3} yard(s), {4} mile(s)".format(m, inch, feet, yard, mile))
Om jeg gjør om 0.0264 til et integer og kjører scriptet så krasjer python fullstendig. Hva er galt?
Jeg kan ikke python, men ville gjort det andre veien. Altså, gjør meter om til et float(eller double eller whatever som er riktig type) og ikke inches til int.
LEIK
Pope's Avatar
Trådstarter
Sitat av Realist1 Vis innlegg
Er det linje 2 du får feilmelding på? Jeg har ikke PC for hånden, så får ikke testet, men min første tanke er at input-funksjonen lagrer input som streng. Prøv m = float(input('...'))
Vis hele sitatet...
Og der var feilen. Jeg må altså tvinge input til å være flyttall.
Har ikke hatt problemer med det tidligere, men da har jeg sikkert ikke forsøkt å multiplisere input med et flyttall heller. Takker og bukker
Input i python 3 er det samme som raw_input i python 2 så vidt jeg vet. Da er det automatisk en string. Så du vet det til senere
LEIK
Pope's Avatar
Trådstarter
Sitat av Likyhane Vis innlegg
Input i python 3 er det samme som raw_input i python 2 så vidt jeg vet. Da er det automatisk en string. Så du vet det til senere
Vis hele sitatet...
Ja, det stemmer at raw_input ble til input i v3. Finnes det andre kommandoer som er bedre egnet for input av integer/float eller er float(input()) beste alternativ?
Sitat av Pope Vis innlegg
Ja, det stemmer at raw_input ble til input i v3. Finnes det andre kommandoer som er bedre egnet for input av integer/float eller er float(input()) beste alternativ?
Vis hele sitatet...
Ut fra mine noe begrensede kunnskaper, så er det den enkleste og beste metoden.
Kjedelig Streiting™
Realist1's Avatar
Ja, float(input()) er standardmetoden, eventuelt caste det der det brukes i stedet. Dvs.:

Kode

m = input('...')
n = float(m)*2.56
Men som regel, så vil du jo lagre variabelen som en float, og dermed bare kjøre float(input()) direkte. (Evt int(input()) da)
På den måten slipper du å ha tallet ditt lagret som string og caste den hver eneste gang du skal bruke den. Bare gjør det med en gang du tar den inn, så er du ferdig med det.

Forøvrig så betyr feilmeldingen du fikk at du kan multiplisere en streng (aka sequence) med en int, men ikke en float. Du vil altså ikke få feilmelding om du multipliserer int og str, men det vil kanskje ikke gi resultatet du ser for deg. Slik går det:

Kode

>>> m = input('Tall: ')
Tall: 6
>>> m*3
'666'
>>> m*3.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
Så, som du ser, du kan fint ta inn et "tall" med input, og deretter multiplisere det med en int n uten å få feilmelding, men resultatet blir bare en streng der "tallet" ditt er plassert inntil seg selv n ganger.
Altså:
'6' * 3 = '666'
'6' * 3.5 = error
Sist endret av Realist1; 2. februar 2018 kl. 17:44.
Det er feil, realist1. Du blander stringoperasjoner og matematiske operasjoner. Int ganget med en string vil gi oppførselen du beskriver, men det er ikke det samme for input() og andre funksjoner. Jeg fant ikke ut av dette med bruk av input(), men noe annet, jeg tror det var noe i Apache Spark. Uansett, under er det to eksempler.

Kode

m = 100.0*input()
n = 100*input()
m vil fungere og regne ut tallet du sendte inn fordi float*input() takler python til å bli en float, den skjønner det implisitt. Mens n blir en int*input(), og python gjør ikke automatisk om fra string til int, og det har med konverteringer å gjøre. Hvorfor blir en lang forklaring jeg ærlig talt ikke er sikker på at jeg kan gjøre tilstrekkelig. Her ser vi rett og slett problemet med språk der du ikke deklarerer datatyper, og det kommer fra en python fan.

Men rent kodemessig er det veldig rotete å gjøre input-kall i en multiplikasjon, det kan være greit for leseligheten å gjøre det klart hva som kommer fra input og ha det som en egen variabel. I eksempelet under kan du bare bruke m så mye du vil senere og det kommer helt klart hva som er input.

Kode

m = float(input("meters: "))
inches = m*2.56
...
Sist endret av Xasma; 2. februar 2018 kl. 18:39.
Kjedelig Streiting™
Realist1's Avatar
Litt usikker på hva det er du mener jeg tar feil på. Greit nok at str*int er en stringoperasjon og ikke en matematisk operasjon, men det er syntaktisk kverulering. Jeg prøver bare å vise hva som skjer når resultatet av input()-funksjonen (som er en string) kjøres mot en float/int med en asterisk som operator, og at jeg bruker ordet "multiplisere" selv om det strengt tatt er en stringoperasjon må da være innafor. Alt annet jeg sier stemmer like fullt.

Dine eksempler vil derimot ikke fungere, noe en kjapp test viser:

Kode

>>> 100.0*input()
5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
>>> 100*input()
5
'5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555'
Altså, som sagt:
str*int funker, str*float funker ikke. Men Python skjønner uansett ikke at parameteren som tas inn i input()-funksjonen er noe annet enn en string, og det er vel hele poenget som trådstarter snublet i.
Sist endret av Realist1; 2. februar 2018 kl. 22:09.
Ja, min bom der, jeg presterte å fyre opp python 2.7.12 istedenfor 3.5 i farten, for der funker det.
▼ ... over en uke senere ... ▼
LEIK
Pope's Avatar
Trådstarter
Jeg har prøvd meg litt videre og laget et lite program som hjelper meg litt i hverdagen. Det åpner egentlig plex, plexpy, rutorrent og et par torrent trackers, men siden URLene inneholder litt privat info har jeg gjort om disse for demonstrating purposes. Til mitt bruk er dette mye mer nyttig enn å åpne en rekke nettaviser, forumer o.l.

Det vanskeligste for meg her ligger i at jeg ikke vil at skriptet skal kjøres ferdig om brukeren gir ugyldige inputs. Dette løste jeg med en while-løkke som ikke brytes før input == en av de gyldige alternativene. Planen var egentlig å lage skriptet med funksjoner da jeg tror dette er mer stuereint, men det fikk jeg ikke til.
Savner GOTO fra batch-skripting

Jeg mistenker at noen brekker seg litt av koden, så jeg ønsker tilbakemeldinger.

Kode

#Imports
import webbrowser, time

#Definerer URLs
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
url_1 = "http://www.freak.no"
url_2 = "http://www.vg.no"
url_3 = "http://www.facebook.com"
url_4 = "http://www.db.no"
url_5 = "http://www.yr.no"

#Start
print ("""Web Launcher
       
Full versjon:
Freak + VG + FaceBook + DB + YR

Lite versjon:
Freak + VG
""")

while True:
    while True:
        version = input("Velg versjon (f)ull / (l)ite: \nLukk programmet ved å skrive e(x)it ")
        version = version.lower()
        if version in ("f", "l", "x"): #Hvis version enten bærer verdien y, n eller x
            break#                 så brytes denne while-løkka. Hvis ikke printes det som står på neste linje og løkka kjøres på nytt.
        print ("Du må velge en gyldig versjon.")
            
    if version == "f":
    
        webbrowser.get(chrome_path).open(url_1)
        webbrowser.get(chrome_path).open(url_2)
        webbrowser.get(chrome_path).open(url_3)
        webbrowser.get(chrome_path).open(url_4)
        webbrowser.get(chrome_path).open(url_5)
        break

    elif version == "l":
        webbrowser.get(chrome_path).open(url_1)
        webbrowser.get(chrome_path).open(url_2)
        break
    
    elif version == "x":
        print("Programmet lukkes")
        time.sleep(2)
        break
Sist endret av Pope; 12. februar 2018 kl. 18:54.
Uten å ha kjørt koden, så ser det ut som den skal fungere ved første øyekast. Var det noe spesielt du lurte på?
LEIK
Pope's Avatar
Trådstarter
Sitat av Pope Vis innlegg
Jeg mistenker at noen brekker seg litt av koden, så jeg ønsker tilbakemeldinger.
Vis hele sitatet...
titegnkreves
Sitat av steili Vis innlegg
Uten å ha kjørt koden, så ser det ut som den skal fungere ved første øyekast. Var det noe spesielt du lurte på?
Vis hele sitatet...
Her er en litt mer komprimert kode. Kanskje du kan få litt inspirasjon fra den (ikke testet, men bør være brukbar)

Kode

# Imports
import webbrowser, time

# Definerer URLs
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
lite_paths = ["http://www.freak.no", "http://www.vg.no"]
full_paths = ["http://www.freak.no", "http://www.vg.no", "http://www.facebook.com", "http://www.db.no", "http://www.yr.no"]

# Start
print ("""Web Launcher

Full versjon:
Freak + VG + FaceBook + DB + YR

Lite versjon:
Freak + VG
""")

while True:
    version = input("Velg versjon (f)ull / (l)ite: \nLukk programmet ved å skrive e(x)it ").lower()
    if version in ("f", "l", "x"):  # Hvis version enten bærer verdien y, n eller x
        break  # så brytes denne while-løkka. Hvis ikke printes det som står på neste linje og løkka kjøres på nytt.
    print ("Du må velge en gyldig versjon.")
if version in ("f", "l"):
    for p in lite_paths if version == "l" else full_paths:
        webbrowser.get(chrome_path).open(p)

print("Programmet lukkes")
time.sleep(2)
Sitat av Pope Vis innlegg
titegnkreves
Vis hele sitatet...
Aha, litt for kjapp der! Leste "mistenker at noe brekker" :-)
Sist endret av steili; 12. februar 2018 kl. 19:20. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
I see you...
NAPse's Avatar
Et par ting som kan være greit å tenke på:
-Ikke importer mer en du har behov for. Begrens det til de delene du faktisk bruker.
-Du har en unødvendig løkke. Og det er generelt god praksis å ikke ha "evige" løkker.

Funkjsoner i et såpass enkelt skript ser jeg ikke den store nytteverdien i, så det mener jeg du ikke trenger.

Forøvrig fungerer skriptet dårlig på min maskin, da den ikke åpner neste fane før jeg lukker hele vinduet.

Mitt løsningsforslag:
SPOILER ALERT! Vis spoiler

Kode

# -*- coding: cp1252 -*-
#Imports
from time import sleep
from webbrowser import get as chrome
     
#Definerer URLs
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'

versions = {"f":#Full
                ["freak.no", "vg.no", "db.no", "facebook.com", "yr.no"],
            
            "l":#Lite
                ["freak.no", "vg.no"],
            
            "pr0n":#Im Twelve Years Old and What is This?
                ["freak.com"]
            }

version = "" #Bare for å ha definert en variabel som kan brukes i while-løkka

#Start
print ("""Web Launcher

Full versjon:
VG + FaceBook + DB + YR

Lite versjon:
Freak + VG
""")
 
while version != 'x':
    version = input("Velg versjon (f)ull / (l)ite: \nLukk programmet ved å skrive e(x)it ").lower()
    if versions.has_key(version): #Hvis dictionary "versions" har gyldig nøkkel ifht. input
        for url in versions.get(version): #For hver url i lista til nøkkel gjør dette...
            chrome(chrome_path).open(url)
            break

print("Programmet lukkes")
sleep(2)


Oops. Den break'en skulle enten ikke vært der i det hele tatt, evt. vært en "indent" bakover.
Sist endret av NAPse; 12. februar 2018 kl. 21:17. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
LEIK
Pope's Avatar
Trådstarter
Sitat av NAPse Vis innlegg
Et par ting som kan være greit å tenke på:
-Ikke importer mer en du har behov for. Begrens det til de delene du faktisk bruker.
-Du har en unødvendig løkke. Og det er generelt god praksis å ikke ha "evige" løkker.

Funkjsoner i et såpass enkelt skript ser jeg ikke den store nytteverdien i, så det mener jeg du ikke trenger.

Forøvrig fungerer skriptet dårlig på min maskin, da den ikke åpner neste fane før jeg lukker hele vinduet.
Vis hele sitatet...
Gode tips

Det du nevner om at skriptet fungerer dårlig opplevde jeg ikke i det hele tatt før jeg kompilerte skriptet til .exe. Da dukket den feilen opp hver eneste gang uten at jeg helt skjønner hvorfor

Jeg tar tipsene deres til meg og forbedrer skriptet.

Så heller ikke hva den tredje "listen" hadde blitt til før jeg begynte i python

Dictionary heter det vel kanskje.

Hva betyr dette: AttributeError: 'dict' object has no attribute 'has_key'
Sist endret av Pope; 12. februar 2018 kl. 21:57. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
Kjedelig Streiting™
Realist1's Avatar
Sitat av Pope Vis innlegg
Hva betyr dette: AttributeError: 'dict' object has no attribute 'has_key'
Vis hele sitatet...
Det betyr at det ikke er noe som heter "has_key" i Python3. Bare bruk "in" i stedet.
LEIK
Pope's Avatar
Trådstarter
takk. Er det en annen feil her og?
I NAPse sitt skript, på linje 33:

if versions.has_key(version):

Dette gjør jeg om til:

if versions in (version): ?
Men det går rett åt skogen med mindre jeg skriver:

if version in (versions): Mulig jeg tar helt feil?
I see you...
NAPse's Avatar
Sitat av Pope Vis innlegg
Hva betyr dette: AttributeError: 'dict' object has no attribute 'has_key'
Vis hele sitatet...
Ehh. Ja, jeg lever i oldtiden og kjører fortsatt py 2.7.
Sånn skal det visst gjøres i dette århundret.

Jeg fikla litt till og fikk det til å fungere med å åpne alle fanene rett etter hverandre. Det er nok ikke den optimale måten å gjøre det på, og er systemavhengig. (Egentlig rene windows kommandoer du kune kjørt med et batch skript.)
Du kan ta en titt om du vil.

SPOILER ALERT! Vis spoiler

Kode

#Imports
from time import sleep
from os import system
     
#Definerer URLs
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe'

versions = {"f":#Full
                ["https://freak.no", "https://vg.no", "https://db.no", "https://facebook.com", "https://yr.no"],
            
            "l":#Lite
                ["https://freak.no", "https://vg.no"]
            }

version = "" #Bare for å ha definert en variabel som kan brukes i while-løkka

#Start
print ("""Web Launcher

Full versjon:
VG + FaceBook + DB + YR

Lite versjon:
Freak + VG
""")
 
while version != 'x':
    version = input("Velg versjon (f)ull / (l)ite: \nLukk programmet ved å skrive e(x)it ").lower()
    if versions.has_key(version): #Hvis dictionary "versions" har gyldig nøkkel ifht. input
        cmd = ""
        for url in versions.get(version): #For hver url i lista til nøkkel gjør dette...
            cmd += 'start "{0}" {1} & '.format(chrome_path, url)
        system(cmd+'exit')
        break

print("Programmet lukkes")
sleep(2)
LEIK
Pope's Avatar
Trådstarter
Æsj, nå datt jeg helt av lasset. Ble litt mange endringer på en gang. Skjønner forsåvidt hvorfor du ønsker å importere system fra os-modulen.
Hva gjør &-tegnet der i linje 32?

for url in versions.get(version): er heller ikke en superintuitiv linje for meg :/

Og hvorfor kan jeg ikke definere variabler for URLs før dictionary defineres? Altså, dict henter ikke inn forhåndsdefinerte variabler.
Sist endret av Pope; 12. februar 2018 kl. 22:20. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
I see you...
NAPse's Avatar
Sitat av Pope Vis innlegg
takk. Er det en annen feil her og?
I NAPse sitt skript, på linje 33:

if versions.has_key(version):

Dette gjør jeg om til:

if versions in (version): ?
Men det går rett åt skogen med mindre jeg skriver:

if version in (versions):
Vis hele sitatet...
Je den skal være "if version in versions:" i python 3.

Sitat av Pope Vis innlegg
Hva gjør &-tegnet der i linje 32?
Vis hele sitatet...
Det er en windows "kommando" for å utføre neste kommando uten å vente på at forrige avslutter. Det har egentlig lite å gjøre med python, så jeg skjønner det er litt forvirrende

Sitat av Pope Vis innlegg
for url in versions.get(version): er heller ikke en superintuitiv linje for meg :/
Vis hele sitatet...
dict.get(key) vil "hente" dataen som ligger under key-en i en dictionary, i dette tilfellet er det en liste som ligger der.

Kode

>>for x in ['hei', 'på', 'deg']:
>>    print x
hei
på
deg
Så det er egentlig det den gjør, den henter en liste og itererer etter den lista.
LEIK
Pope's Avatar
Trådstarter
Og f/l er keys mens urls er dataene i listene som ligger under dict?

Kunne du også svart på dette med å bruke forhåndsdefinerte variabler som innhold i lister (i dicts)?

Setter pris på hjelpen jeg får!
I see you...
NAPse's Avatar
Etter en liten titt i webbrowser.py så jeg dette:
Sitat av webbrowser.py
usage = """Usage: %s [-n | -t] url
-n: open new window
-t: open new tab""" % sys.argv[0]
Vis hele sitatet...
Det første scriptet jeg posta skal fungere(utenom den malpasserte "break"-en) dersom du slenger på et &-teng etter %s i chrome_path.

Sitat av Pope Vis innlegg
Og f/l er keys mens urls er dataene i listene som ligger under dict?
Vis hele sitatet...
Ja, "f" og "l" er keys, og hver av dem inneholder separate data under seg etter kolonet.

Sitat av Pope Vis innlegg
Kunne du også svart på dette med å bruke forhåndsdefinerte variabler som innhold i lister (i dicts)?
Vis hele sitatet...
Jeg skjønner ikke helt hva du mener, men kan prøve å komme med et eksempel til så kanskje det blir lettere å se.

Kode

>>>innlegg_brukere = {'Pope':2323, 'NAPse':251, 'Realist1':2163} 
>>>innlegg_brukere.get('NAPse')
251
>>>innlegg_brukere['NAPse']
251
Sist endret av NAPse; 12. februar 2018 kl. 23:18.
LEIK
Pope's Avatar
Trådstarter
Takk Det jeg mener er at du skriver URLene rett inn i dict. Om jeg har lange URLs hadde det vært greit å lagre de på forhånd under kortere variabelnavn og heller bruke variabelnavnene i dict (versions). Dette får jeg ikke til. Prøver bare å åpne nettsider med url=url_1 , url_2 osv.
Sitat av Pope Vis innlegg
Og hvorfor kan jeg ikke definere variabler for URLs før dictionary defineres? Altså, dict henter ikke inn forhåndsdefinerte variabler.
Vis hele sitatet...
Jeg skjønner ikke helt hvorfor du skulle ønske det. Det virker som det du vil ikke er helt ulikt å definere en variabel først, også bruke det samme navnet til å definere en til med det samme innholdet. En dict består av elementer, hvor hvert element har en nøkkel og et innhold. Du kan like greit definere nøkkelen direkte heller enn å definere en variabel og så ønske å duplisere navn og innhold i dicten.

Det sagt, så ser jeg ikke helt nytten av en dict i dette tilfellet uansett.

Jeg er også enig i at evige løkker – selv om de kan være både nyttige og riktige – som regel bør unngås. Du får en bedre flyt i koden om du allerede ved definisjonen av løkka ser betingelsen for at løkka skal fortsette eller avbrytes.

Når det gjelder bruk av funksjoner, så er det en fordel å bruke når det er mulig å gjenbruke kode – så du slipper å skrive nærmest identisk kode flere ganger i samme program – og for å korte ned veldig lange funksjoner. Men også, vil jeg hardnakket påstå, er det en fordel å bryte ut semantisk separate blokker til funksjoner av flere grunner. I stedet for å ha tre-fire linjer med kode som må forklares med en kommentar på en egen linje, kan du like gjerne bryte den ut til en egen funksjon som er navngitt slik at det er selvsagt nok hva den gjør til at kommentaren blir overflødig. Det gjør at når du leser den opprinnelige kodeblokken trenger du ikke å forholde deg til hvordan det gjøres, bare at det gjøres. Det innfører en "mikro-abstraksjon" som gjør koden enklere å fordøye. Det gjør den mer lesbar, og økt lesbarhet minsker sannsynligheten for å innføre bugs og øker sannsynligheten for å identifisere bugs når noe ikke virker.

Så for å overføre noe av dette til konkrete ting i koden din. (Noe av dette er påpekt og foreslått av andre også.)

Vi kan begynne på toppen. Der har du definert en rekke URLer som hver sin variabel, hvor variablene er nummerert i navnet. Det antyder normalt at en liste eller et array er bedre egnet. Det er også verdt å legge merke til allerede her at dine to modi – Lite og Full – er overlappende i hvilke URLer de skal åpne. Full == Lite + noen_flere. Det kan du utnytte deg av på en måte som gjør det mer oversiktlig og enklere å legge til flere lenker senere. Her ville jeg brukt to lister, en for Lite og en for de som skal legges til i Full:

Kode

urls_basic = ["http://www.freak.no",
              "http://www.vg.no"]

urls_extra = ["http://www.facebook.com",
              "http://www.db.no",
              "http://www.yr.no"]
Det neste du gjør, er å be brukeren om input. Nå kan man diskutere hvor mye hensikt det har å trekke ut dette som egen funksjon, men det gir full mening å gjøre det selv om koden ikke skal gjenbrukes, fordi det å be brukeren om å velge modus for programmet er en semantisk frittstående oppgave som gir mening i seg selv. Og siden du ikke fikk det til, kan vi jo gjøre det her. (Jeg var frekk nok til å bytte version til mode, siden jeg synes det klaffet bedre med hensikten.)

Kode

def prompt_mode():
    user_input = ''
    while user_input not in ['f', 'l', 'x']:
        user_input = input("Velg versjon (f)ull / (l)ite: \nLukk programmet ved å skrive e(x)it ").lower()
    if user_input == 'x':
        print("Programmet lukkes")
        sys.exit()
    return user_input
Det første vi gjør der, er å definere variabelen user_input til en tom streng. Det er fordi vi trenger at den finnes til den skal brukes i while-løkkens betingelse. Deretter setter vi opp løkken: while user_input not in ['f', 'l', 'x'] betyr at så lenge innholdet i user_input ikke er å finne i den lille listen over muligheter vi satte opp, så skal løkka gjenta seg. Så ber vi brukeren om input og gjør det i samme slengen om til lower case for enklere sammenlikning.

Før vi returnerer det brukeren skrev inn, sjekker vi om det var 'x'. Var det 'x' avslutter vi programmet der og da med sys.exit() – men dette krever at vi importerer sys lenger opp. Vi trenger ikke å pakke return user_input inn i en else, fordi det vil aldri kjøre dersom det var 'x', siden programmet da vil avslutte i linjen over.

For å få brukerens input i den generelle kodeblokka, kan vi for eksempel lagre det i en variabel: mode = prompt_mode().

Deretter må vi åpne URLene, og hvilke avhenger av hvilken modus brukeren valgte. Det kan gjøres på flere måter. Det som kanskje er mest rett frem er å sette sammen en ny liste basert på input, slik:

Kode

if mode == 'l':
    urls = urls_basic
elif mode == 'f':
    urls = urls_basic + urls_extra
Og deretter loope gjennom alle elementene i listen og åpne dem. Men det er andre måter å skrive dette på også, for eksempel:

Kode

urls = urls_basic
if mode == 'f':
    urls += urls_extra
# eller ...
urls = urls_basic if mode == 'l' else urls_basic + urls_extra
Videre må man gå gjennom alle elementene for å åpne dem, gjerne da slik:

Kode

for url in urls:
    webbrowser.get(chrome_path).open(url)
Man kan også bli fancy og trekke sammen kode, for eksempel ved å bytte "urls" i for-løkke-uttrykket med uttrykket for urls over, slik:

Kode

for url in urls_basic if mode == 'l' else urls_basic + urls_extra:
Og eventuelt bytte "mode" med funksjonskallet for mode, så det blir slik:

Kode

for url in urls_basic if prompt_mode() == 'l' else urls_basic + urls_extra:
Men det krever litt erfaring i Python før man kan kalle det like lesbart som alternativene. Så i oppsummeringen har jeg valgt den "enklere" metoden:

Kode

import webbrowser
import sys

chrome_path = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s"

urls_basic = ["http://www.freak.no",
              "http://www.vg.no"]

urls_extra = ["http://www.facebook.com",
              "http://www.db.no",
              "http://www.yr.no"]

def prompt_mode():
    user_input = ''
    while user_input not in ['f', 'l', 'x']:
        user_input = input("Velg versjon (f)ull / (l)ite: \nLukk programmet ved å skrive e(x)it ").lower()
    if user_input == 'x':
        print("Programmet lukkes")
        sys.exit()
    return user_input


mode = prompt_mode()

if mode == 'l':
    urls = urls_basic
elif mode == 'f':
    urls = urls_basic + urls_extra

for url in urls:
    webbrowser.get(chrome_path).open(url)
I see you...
NAPse's Avatar
Sitat av Provo Vis innlegg
Det sagt, så ser jeg ikke helt nytten av en dict i dette tilfellet uansett.
Vis hele sitatet...
Jeg kan forklare hvorfor jeg valgte det, men det er absolutt ikke nødvendig. Det er vel først og fremst en smakssak.

Jeg liker å ha kode som er enkel å modifisere i ettertid dersom jeg skulle ønske flere funksjoner i ettertid.
For eksempel dersom han skulle ønske seg en til "version"/"mode" senere trenger man kun legge til en ny nøkkel og tilhørende liste helt i "toppen" av koden uten å måtte endre flere ting.
I ditt eksempel vil man måtte legge til ny liste, endre "while user_input not in ['f','l','x']" og legge til en ekstra elif som skal håndtere den nye input-verdien.

Men som sagt; det er smak og behag.
Sist endret av NAPse; 13. februar 2018 kl. 11:03.
LEIK
Pope's Avatar
Trådstarter
Oi. Provo, tusen takk for et veldig utfyllende svar. Må innrømme at jeg måtte konsentrere meg hardt for å skjønne et par av linjene, men det var overkommelig

Tusen takk til deg og NAPse! Artig å se hvilke kreative innspill dere kommer med.

Jeg foretrekker nok at koden er mest mulig "vanilla python", altså uten altfor mye imports. Dette fordi det er ren Python jeg forsøker å lære og da blir det bare forvirrende med for mye annet snacks

Dette med komprimering av kode er forhåpentligvis noe som blir lettere etterhvert.
LEIK
Pope's Avatar
Trådstarter
Provo: Det eneste Python kicker litt på er sys.exit(). Python sier følgende: warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1). Hvorfor?

Om jeg bruker jeg disse kommandoene for å lukke programmet så kjøres likevel resten av koden.

sys.exit([arg])

Since exit() ultimately “only” raises an exception, it will only exit the process when called from the main thread, and the exception is not intercepted.
Vis hele sitatet...
Altså, siden sys.exit() brukes i en funksjon og ikke i main, så lukkes ikke programmet, men funksjonen avbrytes?

edit: Hmm. Når jeg ser nærmere på det virker det som at resten av koden _ikke_ kjøres, men jeg får likevel en stygg feilmelding.
Spiller kanskje ingen rolle?
Sist endret av Pope; 14. februar 2018 kl. 14:27. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
Merkelig. Hvilken Python-versjon kjører du, og hvordan kjører du scriptet? Det kan se ut som du starter scriptet fra inne i et interaktivt Python-shell av noe slag?

Hele programmet skal lukkes, den avbryter ikke bare funksjonen. Den teksten angår ikke om kallet er i en funksjon, men om det er i en egen tråd. Når man kaller sys.exit() avsluttes tråden den kalles fra, og ikke nødvendigvis hele programmet dersom man har forket eller spawnet flere tråder. Men det er ikke relevant for dette eksempelet.
LEIK
Pope's Avatar
Trådstarter
Ok, jeg forstår. Jeg bruker Python 3.6 i Spyder IDE.
Jeg kompilerte skriptet til .exe og da fungerer alt som det skal.

Jeg ser uendelige muligheter med å bruke Python, men når det kommer til små operasjoner som skal utføres i Windows, som f.eks. skriptet dere har hjulpet meg med, føler jeg at det ikke er noen vits i å bruke slike skript når man likevel må åpne Python for å kjøre de.

Det er derfor jeg kompilerer de så de kan brukes uten Python, men jeg synes pyinstaller, py2exe osv er en kålete måte å kompilere på. Finnes det andre måter å kjøre skriptene på, evt. andre måter å kompilere de på?
Sist endret av Pope; 14. februar 2018 kl. 14:56.
Ser greit ut prove,men 2-space intendering du vet sikkert godt at det burde/skal være 4-space i Python

Her et alternativ du kan se på @Pope,kunne fint ha brukt funksjoner her.
Men en klasse fungere også bra da listene og path kan gjøres i klasse instantiation(__init__).
Når man kjører så faller man alltid tilbake til menu,her kan kjøres igjen eller Quit for komme seg ut.
Ikke noe sys.exit() da en enkel return vil fungere greit her,ettersom det er ingen forurensning i global namespace.

Kode

import webbrowser

class OpenUrl:
    def __init__(self, chrome_path):
        self.chrome_path = chrome_path
        self.urls_basic = [
           "http://www.freak.no",
            "http://www.vg.no"
            ]
        self.urls_extra = [
            "http://www.facebook.com",
            "http://www.db.no",
            "http://www.yr.no"
            ]
        self.menu()

    def open_location(self, urls):
        for url in urls:
            webbrowser.get(self.chrome_path).open(url)

    def menu(self):
        while True:
            print('(L) Lite version')
            print('(F) Full version')
            print('(Q) Quit\n')
            choice = input('Enter your choice: ').lower()
            if choice == 'l':
                self.open_location(self.urls_basic)
            elif choice == 'f':
                self.open_location(self.urls_extra)
            elif choice == 'q':
                return
            else:
                print(f'Not a correct choice: <{choice}>,try again\n')

if __name__ == '__main__':
    chrome_path = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s"
    OpenUrl(chrome_path)
He 2-space på meg og,det er forum som gjør det.

Sitat av Pope
føler jeg at det ikke er noen vits i å bruke slike skript når man likevel må åpne Python for å kjøre de.
Vis hele sitatet...
Det gir jo ingen mening,når du først har Python installert er det klart at man bruker Python til og kjøre koden.
Scenario når man kan kompilere er når man ønsker og dele koden med mange Windows brukere som ikke har Python installert.

Sitat av Pope
men jeg synes pyinstaller, py2exe osv er en kålete måte å kompilere på.
Vis hele sitatet...
pyexe bør ikke brukes ettersom den virker kun til 3.4.
Pyinstaller er det beste valget,også cx_Freeze grei,begge virker 3.6 og er kryssplattform.
Pyinstaller er enkel og bruke,det kan være noe konfigurasjon som må gjøres i noen tilfeller.

Sitat av Pope
Finnes det andre måter å kjøre skriptene på, evt. andre måter å kompilere de på?
Vis hele sitatet...
Mye av det vi gjør i dag er web-basert,så lage en web-app for dele det man lager Python er fullt mulig.
Jeg er fan av Flask,men dette kreves også at men setter seg inn i web-development.

For og dele med andre Python brukere,så bruker man PyPi.
Som betyr at man lager wheel med setup.py.
Da bruker man pip som kommer med Python.

Kode

pip install my_stuff
Eks Requests

Kode

pip install requests
13,000,000 downloads every month. All the cool kids are doing it!
Vis hele sitatet...
Sist endret av snippsat; 14. februar 2018 kl. 17:12. Grunn: Automatisk sammenslåing med etterfølgende innlegg.