'
Pope sliter med Python
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:rolleyes: 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?") |
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?
|
Sitat:
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): Fant løsningen selv. Kode:
def hotel_cost(netter): |
Sitat:
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:
Kode:
def hotel_cost(netter): |
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): Det kan jeg godta, men hvordan vet funksjonen som egentlig er avhengig av nights at den skal bruke days- og ikke city-verdien? |
Sitat:
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): Kode:
Hvor mange netter? 5 |
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. |
Sitat:
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:
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 Kode:
def hotel_cost(netter): kun input() i Python 3. |
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) Kode:
def add2stiffness(ke,local2global,KS): 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?:confused: |
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. |
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. |
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?") 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? |
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('...'))
|
Dette blir rotete, men her er hvertfall et oppdatert skript som i det minste konverterer riktig vei:
Kode:
m = 100*input("Hvor mange meter?") |
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. |
Sitat:
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 :)
|
Sitat:
|
Sitat:
|
Ja, float(input()) er standardmetoden, eventuelt caste det der det brukes i stedet. Dvs.:
Kode:
m = input('...') 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: ') Altså: '6' * 3 = '666' '6' * 3.5 = error |
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() 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: ")) |
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() 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. |
Ja, min bom der, jeg presterte å fyre opp python 2.7.12 istedenfor 3.5 i farten, for der funker det.
|
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 :p Jeg mistenker at noen brekker seg litt av koden, så jeg ønsker tilbakemeldinger. Kode:
#Imports |
Uten å ha kjørt koden, så ser det ut som den skal fungere ved første øyekast. Var det noe spesielt du lurte på?
|
Sitat:
|
Sitat:
Kode:
# Imports Sitat:
|
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 -*- Oops. Den break'en skulle enten ikke vært der i det hele tatt, evt. vært en "indent" bakover. ;) |
Sitat:
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 :confused: 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 :p Dictionary heter det vel kanskje. Hva betyr dette: AttributeError: 'dict' object has no attribute 'has_key' |
Sitat:
|
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? |
Sitat:
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 |
Æ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. |
Sitat:
Sitat:
Sitat:
Kode:
>>for x in ['hei', 'på', 'deg']: |
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! |
Etter en liten titt i webbrowser.py så jeg dette:
Sitat:
Sitat:
Sitat:
Kode:
>>>innlegg_brukere = {'Pope':2323, 'NAPse':251, 'Realist1':2163} |
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:
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", Kode:
def prompt_mode(): 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': Kode:
urls = urls_basic Kode:
for url in urls: Kode:
for url in urls_basic if mode == 'l' else urls_basic + urls_extra: Kode:
for url in urls_basic if prompt_mode() == 'l' else urls_basic + urls_extra: Kode:
import webbrowser |
Sitat:
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. :) |
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. |
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. Sitat:
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? |
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. |
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å? |
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 Sitat:
Scenario når man kan kompilere er når man ønsker og dele koden med mange Windows brukere som ikke har Python installert. Sitat:
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:
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 Kode:
pip install requests Sitat:
|
Alle tidspunkt er GMT +2. Klokken er nå 21:39. |