Introduktion til programmering Uge 40 Python 2 Learning Python, kap 8-12.

Slides:



Advertisements
Lignende præsentationer
Kort om JavaScript Afvikles i browser på klienten Sendes fra server (php, asp, aspx, htm) eller startes i klient som htm/html fil. Skabelon: –”main” -
Advertisements

Stored Procedure Stored Procedure er programstumper, der gemmes i databasen og afvikles op databaseserveren på samme måde som forespørgsler. Med Stored.
1 Problemkompleksitet 2 Problemers kompleksitet En ineffektiv algoritme: køretiden vokser eksponentielt med input- størrelsen Et problem, der ikke kan.
Velkommen til Softwarekonstruktion
Introduktion til programmering
SQL 1 DDL og DML.
Indledende Programmering Uge 2 - Efterår 2006 Selektioner og interaktion mellem objekter Susanne Brix Lindros.
KONCEPT Klasser og objekter En klasse beskriver et World ArrayList
Symbolsk maskinsprog.
Intro Forelæsning 2 Linux install-party lør.14.sept kl – man. 14.okt – Kursets omfang :7,5 ECTS Kursussammensætning: forelæsning.
Hvordan man skriver koden.
Intro Variabler - datatyper. 2. forelæsning Hvad skete sidste gang Hvad er PHP? Kursussammensætning: læse – newsgroup – forelæsning – øvelsestime – aflevering.
Introduktion til Access (Access, del 1)
FEN Diskret matematik/Seminar 3 - proofs 1 Beviser Et bevis er en argumentation, som overbeviser om, at en påstand er sand, påstanden kaldes.
GP5, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 5 Slides ligger på nettet. Du er velkommen til at printe dem nu. Vi begynder.
GP 10, 7/ Grundlæggende programmering Efterår 2001 Forelæsning 10 onsdag 7/ kl. 9:15 – 12:00.
FEN IntroJava AAU1 Java grundelementer Variable og datatyper Sætninger og udtryk Metoder.
Intro Projekttyper v/ Lise Louv, Uddannelsesafdelingen Siden sidst: evaluering på opgaver og virtuel kursus. Kursets ugeforløb læse – forelæsning – øvelsestime.
Operationer på relationer
FEN Prædikater/Seminar 11 Prædikatslogik eller Kvantificerede udtryk Prædikater udvider propositionslogikken på to måder: –Vi tillader variable.
1 HMAK XMLRelationel model og XMLNOEA / PQC 2005 SQLServer og XML Hent data via URL Generering af xml –Raw –Auto –Explicit Hent data via template Evt.
Forelæsning 3.1 Collections Javas for-each løkke
XML og Skemaer Costanza Navarretta Center for Sprogteknologi, Københavns Universitet
Intro til C# apps Kodegennemgang af simpel C# app
Delphi og C++ Builder C++ Builder. C++ Historie Sproget blev designet for AT&T af danskeren Bjarne Stoustrup En objektorienteret videreudvikling.
Program Design – 4 Introduktion til PHP. Dagens lektion Hvad er PHP?  - og lidt historie Hvordan virker PHP? Grundlæggende PHP  Variable  Typer  Løkker.
Introduktion til programmering Uge 38 Python 2 Learning Python, kap 8-12.
W1b1 PC baseret analyse og simulering. w1b2 Definition Digital Elektronisk beregningsmaskine, der har intern hukommelse til lagring af program og mellem-regninger.
1 JavaScript Lektion 6: Repetition i JavaScript Math TIDY Litteratur: JST lektion 10.
FEN KbP/seminar 1: Specifikationer/Notationen Q 1 Kontraktbaseret programmering: Seminar 1 Om specifikationer Algoritmenotationen Q.
Introduktion til Access (Access, del 1). RHS – Informationsteknologi – Fra design til udvikling Vi ved nu, hvordan vi finder et design for en database,
Slide Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 15 Algorithms for Query Processing and Optimization.
Procestræ under afvikling af cp init login shell cp cp src dest.
DIEB4.1 Kursusgang 4 Oversigt: Sidste kursusgang Opgaver Aktivitet 2: Generer design (fortsat) Design af interaktionselementer.
Paradigmer i Programmering 2. Sammensatte typer Tupler og lister Programmering med rekursion Programmering med pipe-lines Programmering med polymorfe.
Paradigmer i Programmering 1. Program for idag : Funktioner og udtryk i SML : Øvelse : Frokost – 14.00: Deklarative.
8 RÅD VEDRØRENDE GOD PROGRAMMERING Effective (brown) Java.
FEN IntroJava AAU1 Klasser og objekter Grundbegreber Student-Course.
Oprettelse af tabeller (Access, del 2)
C#: Udtryk og metoder Kilde: Joe Hummel. 2 Nordjyllands Erhvervakademi – 2008 Indhold “With regards to programming statements and methods, C# offers what.
03 – Udtryk og metoder. 2 NOEA2009Java-kursus – Udtryk og metoder Udtryk i Java Java har standard udtrykene… Værditildeling Subrutiner og funktionskald.
SQL – Oracle Vigtige SQL sætninger Lektion 6 7. Semester.
PD – kursusgang 3 Introduktion til Java Script. Mål Viden om hvordan JavaScripts indlejres i HTML dokumenter Viden om programmering i JavaScript  Erklæring.
Intro Siden sidst: evaluering på opgaver og virtuel kursus.
Intro Siden sidst: evaluering på opgaver og virtuel kursus Kursussammensætning: forelæsning – læse – arbejde selvstændigt – newsgroup – øvelsestime – aflevering.
Opfølgning på Dygtig Skildpadde (Michael) To algoritmeskabeloner findEn findAlle Primitive typer (forfremmelse og begrænsning) Identitet versus lighed.
GP4, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 4 Vi begynder Slides ligger på hjemmesiden. Du er velkommen til.
Paradigmer i Programmering 3. Højere ordens funktioner Idag: Højere ordens funktioner Algebraiske datatyper Næste gang: I/O, Filer, interaktive programmer.
Effective Java Blå gruppe. Item 18: Interfaces frem for abstrakte klasser Kan implementeres i klasser der ikke nedarver Eksisterende klasser kan nemt.
Intro Siden sidst: evaluering på opgaver og virtuel kursus.
Klasser og objekter. dIntProg, E08Klasser og objekter.2 Grundbegreber Klasser og objekter –beskrivelse –oprettelse Attributter og metoder –tilstand –opførsel.
DAIMIIntroducerende objektorienteret programmering3B.1 Definition af klasser Klasseskelet, metoder, et eksempel: dato.
Objekt-relationel DBMS1 4.5 The Object-Relational Model 9.4 User-Defined Types in SQL 9.5 Operations on Object-Relational Data Ullman: Object-Relational.
 Jens Bennedsen 2001Multimedie programmering4.1 Definition af begreber Interface, implements, klasse.
Klasser og objekter. dIntProg, F08Klasser og objekter.2 Grundbegreber Klasser og objekter –beskrivelse –oprettelse Attributter og metoder –tilstand –opførsel.
Jesper Mosegaard Multimedie Programmering E2003 MMProg uge44 Java til Lingo Klasser, statements og lister.
Multiple processer på web-site Web- server filer Kunde 1 Kunde 2 Kunde p1p2p internet.
Forelæsning Uge 2 – Torsdag Java syntax og style guide Sætninger –Simple sætninger (assignment, interne og eksterne metodekald) –Sammensatte sætninger.
Forelæsning Uge 2 – Torsdag
Forelæsning Uge 4 – Mandag
Forelæsning Uge 2 – Mandag
1587 Server - Blandet miljø Webintegrator HF1
IOT – Elkedel på internettet
Klasser og objekter (Afsnit i manualen).
Dokumentation.
Modellering og data Nyt forløb.
Dokumentation.
Dokumentation.
Programmering.
Forelæsning Uge 4 – Torsdag
Præsentationens transcript:

Introduktion til programmering Uge 40 Python 2 Learning Python, kap 8-12.

Plan Opsamling ER-diagrammer og SQL Sidste gang Sætninger og udtryk Kontrolstrukturer  Selektion If…:  Gentagelse While…: For…: Øvelse 1 Funktioner Stand-up programmering Dokumentation Øvelse 2

ER-diagrammer og SQL En tabel består typisk af mindst to kolonner Intern repræsentation (ID) ændrer sig aldrig. Det gør ekstern repræsentation såsom nummeret på et sæde osv. Hvis der f.eks. Kommer flere sæder eller færre

Afleveringer Har alle afleveret deres øvelsesopgaver? Husk det! Det har betydning for hvilken eksamensform i skal gå op i

Html og css bog? Har bogen som e-book

Sidste gang Navne, værdier og typer Objekter Type(værdi) (string) Id(variabel) (x45hx344) Simple typer (scalarer)  Tekst (string), index, slicing  Tal (int, float) Sammensatte typer  List []  Tuple ()  Dictionary () Udtryk – skabe nye værdier (”peter”[::-1])

Repetition af udtryk 'Peter'[1:3][::-1] = 'te’. Hvorfor?

Udtryk Udtryk (expression): noget der repræsenterer en værdi  1 repræsenterer et heltal  ’Peter’ repræsenterer en tekst (string) Et sammensat udtryk er en kombination af andre udtryk og operatorer der repræsenterer og producerer en (ny) værdi  repræsenterer 3 –et tal (1 og 2 = udtryk, + = operator)  'Peter'[1:3] repræsenterer 'et’ – en tekst  [1,2,3][1] repræsenterer 2 – et tal  [1,2,3][0:2] repræsenterer [1, 2] – en liste  [1:3] repræsenterer en operation

'Peter'[1:3][::-1] = 'te’. Hvorfor? Fortolkningen af udtryk består i at frembringe det objekt de repræsenterer Repræsentation Objekt Fortolkning

'Peter'[1:3][::-1] = 'te’. Hvorfor? 'Peter'[1:3][::-1] Peter et te slicing R O I R O I R O I R O I Repræsentationer der er aflæselige for mennesker Repræsentati oner der er aflæselige for maskinen R O I

Sætninger og udtryk Programmer består af et eller flere moduler Moduler består af sætninger (statements) Sætninger indeholder udtryk Udtryk repræsenterer og producerer værdier Sætninger  Sætninger repræsenterer ikke værdier  Sætninger regulerer hvordan værdierne produceres Eksempel  >>> len('peter') 5  >>> x = 'peter’ >>> Udtryk: producerer 5 sætning: producerer ingenting men ændrer variables værdier

Påstande – Boolske udtryk Udtryk der repræsenterer værdierne sand eller falsk.  De repræsenterer værdierne 1 og 0 (i nyere versioner True og False) Naturlige sprog: påstande Bussen går kl Det er løgn! Nogle sproghandlinger som ordrer kan hverken være sande eller falske Gå nu op i bussen. Det er løgn – lyder mærkeligt, men kan siges. >>> == 4  True >>> 'Peter' == 'Karl’  False >>> 'Peter' <> 'Karl’  True

Sandhedsværdier Boolske operatorer  And, or, not  Boolske udtryk producerer nye sandhedsværdier af gamle sandhedsværdier >>> 1+2 == 3 and 4+5 == 9  True >>> not (1+2 == 3 and 4+5 == 9)  False >>> (1+2 == 3 or 1+2 == 9)  True

Sandhedstabeller pqp and q true false truefalse pqp or q true falsetrue falsetrue false pNot p truefalse true

Nye operatorer kan defineres ved de gamle pqNot pnot (p) or q true falsetrue false true false true

Naturlige sprog og logiske Naturlige sprog lægger en årsagsfortolkning ind i hvis-så Det gør logikken ikke Hvis = 5, så vinder socialdemokraterne næste valg  Logisk: altid sand fordi = 5  Naturligt sprog: nonsens (eller ironisk) fordi der ikke er nogen årsagssammenhæng pqNot pnot (p) or q true falsetrue false true false true

If-kontrolstruktur (sætning) if : er en selektionsstruktur skal repræsentere en sandhedsværdi Handlingssætningerne udgør en blok Blokke er indenteret med tabulator eller mellemrum Brug tabulator ikke mellemrum det bliver noget rod if :

’if’ if-sætninger kan indeholde mange forskellige betingelser if : #indledende elif : #ellers hvis else: #hvis intet var sandt

Porfyrs træ if raw_input('Legemlig substans?') == 'ja': print 'Ja. Legemlig substans' if raw_input('levende?')== 'ja': print 'Ja.Levende organisme' if raw_input('Ja. Sansende?')== 'ja': print'Ja. Et dyr' if raw_input('rationelt?')== 'ja': print 'Ja. Rationelt dyr' if raw_input('dødelig?')== 'ja': print 'Ja. Et menneske' else: print 'Nej. Gud' else: print 'Nej. Et dyr' else: print 'Nej. En plante' else: print 'Nej. Død natur (sten, jord)' else: print 'Nej. Et begreb'

Eksempler Eksempel 1  Legemlig substans?  Ja. Kropslig  levende?  Ja.Levende organisme  Sansende?  Ja. Et dyr  rationelt?  Ja. Rationelt dyr  doedelig?  Nej. Gud Eksempel 2  Legemlig substans?  Ja. Kropslig  levende?  Ja.Levende organisme  Sansende?  Nej. En plante

While-loop While :  Statement  … Checker om er sandt. Hvis det er, udføres den efterfølgende blok. Ellers springes til det statement der følger efter blokken

While i et program (optælling) filename = raw_input('Indtast navn på file: ') if filename == '': filename = 'entekst.txt' myfile = open(filename,'r') ##open the file aline = myfile.readline() ##read the first line from the file nol = 0 #number of lines now = 0 #number of words while aline <> '': #as long as aline is not empty nol += 1 #increase the linecounter thewords = aline.split(' ')#split the line into words now = now + len(thewords)#increase the word counter by the number of words aline = myfile.readline()#read the next line from the file print 'The number of lines is ' + str(nol) print 'The number of words is ' + str(now)

For-loop For in :  Statement  … Navn kommer til at referere til medlemmerne af, fra første til sidste Meget hyppigt brugt

Select med OR-betingelse resultat = [] #gennemløb alle rækker i tabellen for row in tabel: #gæt på at rækken ikke duer success = False #gennemløb alle stikord i betingelsen for keyword in requirement.keys(): #hvis værdien af stikordet i betingelsen = værdien af stikordet i rækken if requirement [keyword] == row[keyword]: #rækken duede alligevel success = True #hop ud af løkken break if success == True: #hvis rækken duede, tilføj rækken til resultatet resultat.append(row) tabel = [{'fornavn':'Peter','efternavn':'Andersen','adresse':'Vestergade'}, {'fornavn':'Karen','efternavn':'Jensen','adresse':'Oestergade'}, {'fornavn':'Hans','efternavn':'Karlsen','adresse':'Vestergade'}] requirement = {'adresse':'Vestergade', 'efternavn':'Jensen'} SELECT * FROM tabel WHERE adresse = ”Vestergade OR efternavn = ”Jensen”

Afbrud af løkker Break: hopper ud af den inderste loop Continue: hopper op til loopens betingelse Pass: gør ingenting. Kan også bruges i if-konstruktioner, funktioner osv. Kan bruges hvis vi ikke helt ved hvad der skal stå i sætningen endnu, men vi ved den skal med

Øvelse 1 Lav en pengemaskine der kan give tilbage på et hvilket som helst beløb i mønterne 1, 2, 5, 10, 20 Øvelsen ligger på hjemmesiden

Funktioner Funktioner er en måde at gruppere sætninger så de kan kaldes igen og igen Et funktionsnavn repræsenterer et funktionsobjekt (callable object) Det er en måde at strukturere et program i overskuelige enheder To keywords:  def : sætter et navn til at referere til et funktionsobjekt  return: får funktionen til at returnere en værdi (et objekt)

Funktioner def funktionsnavn ( param1, param2,..., paramN):  sætning1  sætning2 ...  sætningN  return resultat

Eksempel def udskrivOmvendt(tekst):  return tekst[::-1] >>>x = udskrivOmvendt('peter') >>> x  'retep’ Funktionens navn Parametrene Beskrivelse af selve funktionen (callable object) Vi kan give alle typer af parametre med der kan slices også lister

Pass by reference Parameternavne refererer til samme objekt som de aktuelle parametre Samme objekt hedder to forskellige ting Pas på! x = [1,2,3] def func(y): del(y[0]) >>> func(x) >>> x [2, 3] x y [1,2,3] RO R O funktion Intern repræsentation i funktionen

Scope Navne der oprettes inden i en funktion er forskellige fra identiske navne der bruges uden for funktionen Det område hvor et navn gælder kaldes dets scope Det er altid det mindste scope der gælder Deres reference er også forskellige Analogi:  I familiens skød betyder ’Anders’ snothvalpen henne i sofaen  I den politiske offentlighed betyder ’Anders’ Danmarks statsminister Sæt nuværende_scope til det omgrænsende scope af navnets forekomst Så længe vi ikke har fundet navnet:  Findes navnet i nuværende_scope: Ja. Bruge dette navns reference Nej: sæt nuværende_scope til det omgrænsende scope af nuværende_scope Hvis vi ikke har fundet navnet  Giv en fejlmeddelelse

Eksempel a = "karsten" def funktion(): a = "anders" print a funktion() #kald funktionen print a #udskriv det der står uden for funktionen >>> #output anders karsten

Globale og lokale variable def func(): z =[] z = [1,2,3] func() z  [1, 2, 3] def func() global z z = [] func() z  [] 1,2,3 [] Hvis ikke opretter vi en ny lokal variabel Ingen assignment derfor leder den opad i scopet

Funktionsværdier Et funktionsnavn refererer til en værdi med typen ’function’ >>> type(func)  >>> Derfor kan man tildele et andet navn funktionsobjektet som værdi

To funktioner def union (sekvens1, sekvens2): #foreningsmængde  resultat = sekvens1[:]  for x in sekvens2: if not(x in sekvens1):  resultat.append(x)  return resultat def intersection(sekvens1,sekvens2): #overlap  resultat = sekvens1[:]  for x in sekvens1: if not(x in sekvens2):  resultat.remove(x)  return resultat

Funktionsnavne Man kan sætte et andet navn til at referere til funktionsobjektet >>> foreningsmængde = union >>> foreningsmængde([1,2,3],[4,6]) [1, 2, 3, 4, 6] Man kan også bruge et funktionsnavn som parameter i en anden funktion funktion[1,2,3][4,5,6] [1, 2, 3, 4, 5, 6] union foreningsmængde

Funktioner som parametre def do(sekvens1,funktion, sekvens2): return funktion(sekvens1, sekvens2) I overskriften optræder funktionen som parameter - som data der flyttes I kroppen optræder funktionen som noget der kan kaldes Von Neumann igen!

Funktionsnavn og funktionsresultater do er en metafunktion der sætter andre funktioner sammen med deres argumenter print do([1,2,3],union,[3,4,5])  [1, 2, 3, 4, 5] Funktionsnavnet union bruges som parameter og dets værdi udføres i do funktionen. Resultatet af funktionskald kan også også bruges som parameter print intersection( union([1,2,3],[3,4,5]),[1,4])  [1, 4] Resultatet af Union ([1,2,3],[3,4,5]), nemlig [1, 2, 3, 4, 5], gives som parameter til Intersection hvis anden parameter er [1,4] Union repræsenterer en funktion Union ([1,2,3],[3,4,5]) repræsenterer en liste.

Returnering af flere værdier fra en funktion Brug en tupel Brug tupel-unpacking def funktion(a,b):  res1 = a+b  res2 = a* b  res3 = a-b  return (res1,res2,res3) x,y,z = funktion(23,34)

Funktionsnavne Giv altid funktioner sigende navne der beskriver hvad funktionen gør Hvis det er svært at finde på et navn, eller navnet bliver meget langt, er det fordi at flere funktioner er blevet indlejret i den samme funktion og funktionen bør derfor splittes op i flere funktioner sorterUdskrivOgGemTeksten() #ikke et godt navn, hvad nu hvis vi kun ville gemme

if __name__ == “__main__”: Hvordan undgår man at få udført eventuelle sætninger i et modul? def f1(): pass def f2(): print “Morten” if __name__ ==”__main__”:  f1()  f2() Bruges typisk til tests

Opsummering Store dele af Python kan forstås gennem følgende simple model: En repræsentation/udtryk står for et objekt/en værdi Fortolkningen af et udtryk producerer det objekt som repræsentationen står for Kombinationen af en funktion/operation plus andre værdier producerer en nye værdi Et funktionsnavn står for et funktionsobjekt  print intersection  RepræsentationObjekt, VærdiEksempel Simpelt udtrykListe, tekst, tupel, boolsk værdi, dictionary, heltal [1,2,3], ’peter’, (2,3,4), True OperationerOperation[1:3], and, + Sammensatte udtrykVærdien af udtrykketstr((12+34))[1] == ’6’, 1 > 2 == False FunktionsnavnfunktionsobjektudskrivOmvendt repræsenterer 0x011851B0 der igen repræsenterer et funktionsobjekt FunktionskaldVærdien af det der returneres udskrivOmvendt (”peter”) repræsenterer en streng

Moduler Moduler er Python-programmer der kan bruges fra andre Python-programmer Læg jeres moduler i den samme mappe De ”importeres” ved at bruge kommandoen import.  Import  From import * Moduler kan indkapsle en verden man ønsker at bruge men ikke at forstå. Modulet beskriver hvordan dets verden fungerer i detaljer men man behøver kun at vide hvordan man bruger dets verden Vi tager alle funktionerne ud af programmet og lægger dem i et modul. Når vi skal skrive et program der benytter sig af modulets funktionalitet, importerer vi modulet. typisk samle funktioner inde for samme problemdomæne, f.eks. Math, persistens osv. så vi ved hvad modulet kan bruges til

Stand-up programmering Lav et modul der kan analysere tekster Modulet skal kunne:  Fjerne alle karakterer der ikke er ord  Give mulighed for at ændre hvilke karakterer der ikke er ord  Analysere hvor mange antal ord der er i teksten  Give svar på antal forekomster af hvert ord i teksten

Sigende funktionsnavn igen Hvert funktionsnavn havde i vores tekst analyse_modul sigende navne hvilket gør det nemt for andre at forstå hvad modulet gør og hvordan det skal bruges  stripNonCharacters  getWordCount  getWordCountDictionary Hvis funktioner havde hedet a, b, c havde de været svære at forstå

Kommentarer & Docstring Kommentarer i pythonprogrammer starter med # Kommentarer ignoreres af fortolkeren Docstring er en kommentar der gemmes med koden def funktion():  “”” Dette er en docstring “””  Pass Eksempel fra text_module_finished

Docstring dir(str), dir(list) liste over attributter og funktioner help(str.startswith) hjælp til den specifikke funktion Dir(text_module) Help(text_module) Help(text_module.stripNonCharaters)

Dir >>> dir(text_module_finished) ['__builtins__', '__doc__', '__file__', '__name__', 'getWordCount', 'getWordCountDictionary', 'nonWords', 'nonWordsSpeciels', 'setNonWordsList', 'stripNonCharacters']

Help >>> help(text_module_finished) Help on module text_module_finished: NAME text_module_finished - # -*- coding: ISO *- FILE d:\documents\ito e07\peter bv\uge 40\programs\text_module_finished.py FUNCTIONS getWordCount(string, strip=True) string => a string containing words for counting strip => optional, default = True: should the string be stripped for non-word characters before count i performed? return: an integer value representing the count getWordCountDictionary(string, strip=True) string => a string containing words for counting strip => optional, default = True: should the string be stripped for non-word characters before count i performed? return: a dictionary where each word in the string represent a key and each value is the count of the specific word setNonWordsList(nonW, nonWordsS) nonW => a list of characters which should not be treated as words and therefore should be replaced with "" nonWordsS => a list of characters which should not be treated as words but represent a special character which should followed by a space e.g. newline, tab, slash stripNonCharacters(string) string => the string which should be stripped from non-word characters return: a string stripped from non-word characters DATA nonWords = [',', '.', '!', '?', '"', "'", '(', ')', ';', '_', '-', '--... nonWordsSpeciels = ['\n', '\r', '\t', '/']

Docstrings I text analyse modulet  def stripNonCharacters(string):  """  string => the string which should be stripped from non-word characters  return: a string stripped from non-word characters  ""“ I prompten >>>help(text_module_finished.stripNonCharacters)  Help on function stripNonCharacters in module text_module_finished:  stripNonCharacters(string)  string => the string which should be stripped from non-word characters  return: a string stripped from non-word characters

Øvelse 2 Med udgangspunkt i den kode i lavede sidste gang skal i nu analysere hvorvidt det indtastede cpr-nummer er gyldigt eller ej. Aflevering: korrekt python kode til øvelse 1 og 2