{
  "assessmentTests": {
    "python_test": {
      "name": "Python-test",
      "desc": "30 scenariofrågor om syntax, funktioner, datastrukturer och objektbeteende — ta reda på om din Python överensstämmer med vad en jobbannondering menar med Python-kompetens.",
      "recommendation": "Din Python-kompetensprofil",
      "results": {
        "beginner": {
          "name": "Nybörjare",
          "desc": "Du kan följa ett kort skript och ändra värden inuti det, men frågorna du missade klustras kring språkets egna specifika beteende snarare än allmän logik — ett standardargument som byggs en gång och återanvänds, is mot == på två likvärdiga listor, en variabel som blir lokal i det ögonblick du tilldelar den någonstans i en funktion. Inget av detta handlar om att vara dålig på programmering; dessa är Python-specifika regler som stoppar människor från andra språk lika ofta som nybörjare. De är viktiga på jobbet eftersom var och en av dem är där ett fel gömmer sig i kod som ser korrekt ut vid en snabb blick.",
          "recommendation": "Börja med tre saker, i den här ordningen: föränderliga standardargument (varför basket=[] är farligt), skillnaden mellan is och ==, och hur variabelomfattningen fungerar inuti en funktion. Den officiella Python-handledningen på docs.python.org täcker alla tre direkt, och termen \"Python gotchas\" ger många genomarbetade exempel på var och en."
        },
        "intermediate": {
          "name": "Medelnivå",
          "desc": "Du hanterar dagligt skriptande bekvämt — datastrukturer, kontrollflöde, enkla funktioner — och skulle inte bromsa ner av rutinmässigt underhållsarbete eller en liten funktion i en befintlig kodbas. Gapet mellan här och Avancerad är mestadels i vad som händer när Pythons bekvämlighetsfeatures interagerar med varandra: en grund kopia som lämnar kapslade data delade när du förväntade dig att den skulle dupliceras, en generators returvärde som tyst inte blir en del av dess utdata, dekoratörer som staplas i en ordning som är lätt att få bakvänds. Det är den sort av buggar en senior-granskare flaggar på tio sekunder och alla andra tillbringar en timme med att jaga.",
          "recommendation": "Fokusera på objekt- och iterationsinternals: grund mot djupt kopiera, vad en generator faktiskt gör med return, och hur dekoratör-staplings ordning fungerar. Sedan klassgrunderna som de flesta handledningar hoppar över — standardequalitet utan __eq__, och varför en föränderlig klassattribut är delad mellan varje instans."
        },
        "advanced": {
          "name": "Avancerad",
          "desc": "Det här är nivån som de flesta jobbannonseringar menar med \"stark Python.\" Du griper efter rätt verktyg utan att behöva leta efter det, du vet varför en bit delat tillstånd ändrades snarare än bara att det gjorde det, och du kan läsa någon annans funktion och förutse dess utdata korrekt. Det som skiljer det här bandet från toppen är försidans arbetssätt: att veta vilken av två korrekt utseende tillvägagångssätt som kommer att fungera dåligt när en klassattribut, ett nyckelord-endast argument eller en exceptionshierarki är inblandad.",
          "recommendation": "Pusha in i de delar som skyddar en kodbas som andra människor också rör: nyckelord-endast argument som ett API-designval snarare än en syntaxnyckenhet, exceptionshierarkin (så except-satser fångar rätt familj av fel, inte bara en klass), och kontexthanterare som standardsättet att garantera rensning. Real Pythons djupgravande artiklar är en bra nästa stoppplats för alla tre."
        },
        "expert": {
          "name": "Expert",
          "desc": "Du fick topprésultat i varje sektion — kärnasyntax, funktioner och omfattning, datastrukturer och objektorienterade idiom. Praktiskt taget betyder det att du kan få en främling fil och förklara varför den producerar den utdata den gör, inte bara vad syntaxen säger att den borde göra, vilket är det svårare och mer värdefullt färdigheterna. På denna nivå är det råa språket sällan den begränsande faktorn i ditt arbete; gränsen är vanligtvis storleken eller formen på systemet runt koden.",
          "recommendation": "Avkastningen ligger nu i verktyg och granskning: statisk typkontroll med mypy eller pyright, profilering före optimering snarare än gissning, och läsning av andra människors pull-förfrågningar för exakt denna kategori av fel — de som passar varje test och gör ändå fel under en specifik inmatning. Om du screenes för en roll, beskriv en sådan fel som du hittade snarare än att namnge språkfunktioner — det demonstrerar resonemanget, inte bara vokabulären."
        }
      },
      "questions": [
        {
          "question": "Du skriver def add_item(item, basket=[]): basket.append(item); return basket, sedan anropar du add_item('a') och add_item('b'), båda gångerna utan att lämna basket. Vad returnerar det andra anropet?",
          "options": [
            {
              "icon": "",
              "label": "['b'] — varje anrop får en färsk tom lista per standard"
            },
            {
              "icon": "",
              "label": "TypeError — du måste tillhandahålla ett basket-argument"
            },
            {
              "icon": "",
              "label": "['a', 'b'] — standardlistan skapas en gång och återanvänds mellan anrop"
            },
            {
              "icon": "",
              "label": "['a'] sedan ['b'] som två oberoende enbokstavade listor"
            }
          ]
        },
        {
          "question": "a = [1, 2, 3] och b = [1, 2, 3]. Vad returnerar a == b, och vad returnerar a is b?",
          "options": [
            {
              "icon": "",
              "label": "Sant för båda — identiska listor är alltid samma objekt"
            },
            {
              "icon": "",
              "label": "Sant för ==, Falskt för is — lika innehål men olika objekt i minnet"
            },
            {
              "icon": "",
              "label": "Falskt för båda — separata litteraler är aldrig lika i Python"
            },
            {
              "icon": "",
              "label": "Sant för is, Falskt för == — is kontrollerar värdejämlikhet för listor"
            }
          ]
        },
        {
          "question": "I Python 3, vad utvärderas 7 / 2 till, och vad utvärderas 7 // 2 till?",
          "options": [
            {
              "icon": "",
              "label": "3.5, sedan 3 — / returnerar alltid en float, // avrundar resultatet"
            },
            {
              "icon": "",
              "label": "3, sedan 3.5 — / trunkerar och // returnerar en float"
            },
            {
              "icon": "",
              "label": "3.5, sedan 3.5 — båda operatörer returnerar en float i Python 3"
            },
            {
              "icon": "",
              "label": "3, sedan 3 — båda operatörer avrundar resultatet i Python 3"
            }
          ]
        },
        {
          "question": "s = 'hello', sedan kör du s[0] = 'H'. Vad händer?",
          "options": [
            {
              "icon": "",
              "label": "s blir 'Hello'"
            },
            {
              "icon": "",
              "label": "s blir 'Hhello' eftersom tecknet infogas, inte ersätts"
            },
            {
              "icon": "",
              "label": "TypeError — strängar är oföränderliga och stöder inte itemtilldelning"
            },
            {
              "icon": "",
              "label": "Inget — tilldelningen ignoreras tyst och s förblir 'hello'"
            }
          ]
        },
        {
          "question": "x = [10, 20, 30, 40, 50]. Vad returnerar x[1:4]?",
          "options": [
            {
              "icon": "",
              "label": "[20, 30, 40, 50]"
            },
            {
              "icon": "",
              "label": "[10, 20, 30, 40]"
            },
            {
              "icon": "",
              "label": "[20, 30, 40]"
            },
            {
              "icon": "",
              "label": "[30, 40]"
            }
          ]
        },
        {
          "question": "name = 'Ana' och age = 30. Vad producerar f'{name} is {age}'?",
          "options": [
            {
              "icon": "",
              "label": "{name} is {age}"
            },
            {
              "icon": "",
              "label": "Ana is 30"
            },
            {
              "icon": "",
              "label": "name is age"
            },
            {
              "icon": "",
              "label": "En TypeError, eftersom f-strängar kräver format()-metoden"
            }
          ]
        },
        {
          "question": "Vad utvärderas 1 < 2 < 3 till?",
          "options": [
            {
              "icon": "",
              "label": "Sant — Python kedjar jämförelserna som (1 < 2) and (2 < 3)"
            },
            {
              "icon": "",
              "label": "Falskt — kedjade jämförelser utvärderas från vänster till höger utan kortslutning, vilket ger 1 < 2 < 3 -> 1 < Sant -> Falskt"
            },
            {
              "icon": "",
              "label": "Ett SyntaxError — jämförelser kan inte kedjas"
            },
            {
              "icon": "",
              "label": "3 — Python returnerar det sista värdet i kedjan"
            }
          ]
        },
        {
          "question": "Vad returnerar bool([]), och vad returnerar bool([0])?",
          "options": [
            {
              "icon": "",
              "label": "Falskt, sedan Falskt — varje lista innehållande endast falsiska värden är falsk"
            },
            {
              "icon": "",
              "label": "Falskt, sedan Sant — en tom lista är falsk, en lista innehållande ett element (även 0) är sann"
            },
            {
              "icon": "",
              "label": "Sant, sedan Sant — icke-None-objekt är alltid sanna"
            },
            {
              "icon": "",
              "label": "Sant, sedan Falskt — en lista är sann endast när den är tom"
            }
          ]
        },
        {
          "question": "En modulnivå count = 0 finns. Inuti def increment(): count += 1; return count, anropar du increment(). Vad händer?",
          "options": [
            {
              "icon": "",
              "label": "UnboundLocalError — att tilldela till count någonstans i funktionen gör den lokal, så count += 1 försöker läsa en lokal variabel innan den är tilldelad"
            },
            {
              "icon": "",
              "label": "Det returnerar 1 och ökar modulnivåns count till 1"
            },
            {
              "icon": "",
              "label": "Det returnerar 1 men lämnar modulnivåns count på 0"
            },
            {
              "icon": "",
              "label": "Det höjer NameError eftersom count aldrig deklarerats inuti funktionen"
            }
          ]
        },
        {
          "question": "def f(*args, **kwargs): return args, kwargs. Vad returnerar f(1, 2, x=3)?",
          "options": [
            {
              "icon": "",
              "label": "([1, 2], {'x': 3})"
            },
            {
              "icon": "",
              "label": "((1, 2), {'x': 3})"
            },
            {
              "icon": "",
              "label": "(1, 2, {'x': 3})"
            },
            {
              "icon": "",
              "label": "TypeError — positionella och nyckelord-argument kan inte blandas i ett anrop"
            }
          ]
        },
        {
          "question": "Du bygger funcs = [lambda: i for i in range(3)] i en loop. Vad returnerar [f() for f in funcs]?",
          "options": [
            {
              "icon": "",
              "label": "[2, 2, 2] — varje lambda slår upp i när den anropas, och då har loopen avslutats med i lika med 2"
            },
            {
              "icon": "",
              "label": "[0, 1, 2] — varje lambda fångar värdet av i när den skapades"
            },
            {
              "icon": "",
              "label": "[0, 0, 0] — lambdas fångar alltid det första värdet tilldelat till en variabel"
            },
            {
              "icon": "",
              "label": "Ett NameError, eftersom i inte längre finns när loopen slutar"
            }
          ]
        },
        {
          "question": "En funktion definieras med @a direkt ovan @b, vilket sitter direkt ovan def f(): pass. I vilken ordning tillämpas dekoratörerna på f?",
          "options": [
            {
              "icon": "",
              "label": "b omsluter f först, sedan omsluter a resultatet av b — dekoratören närmast funktionen körs först"
            },
            {
              "icon": "",
              "label": "a omsluter f först, sedan omsluter b resultatet — dekoratörer tillämpas uppifrån och ned"
            },
            {
              "icon": "",
              "label": "Båda dekoratörerna omsluter f oberoende och endast den sista definierade tar effekt"
            },
            {
              "icon": "",
              "label": "Det beror på ordningen dekoratörerna importeras, inte deras position i koden"
            }
          ]
        },
        {
          "question": "def f(a, *, b): return a + b. Vilket av dessa anrop fungerar?",
          "options": [
            {
              "icon": "",
              "label": "f(1, b=2) — b måste skickas genom nyckelord eftersom det kommer efter det nakna * i signaturen"
            },
            {
              "icon": "",
              "label": "f(1, 2) — positionella argument fyller parametrar från vänster till höger oavsett *"
            },
            {
              "icon": "",
              "label": "f(a=1, 2) — nyckelord-argument måste komma först"
            },
            {
              "icon": "",
              "label": "f(1) — b är valfritt eftersom det följer *"
            }
          ]
        },
        {
          "question": "En generatorfunktion ger 1, sedan ger 2, sedan gör return 99. Vad innehåller list(the_generator()), och vad händer med 99?",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 99] — return inuti en generator beter sig som ett till yield"
            },
            {
              "icon": "",
              "label": "[99] — return åsidosätter omedelbar alla värden som redan har givits"
            },
            {
              "icon": "",
              "label": "[1, 2] — returvärdet för en generator blir värdet kopplat till StopIteration som den höjer, det är inte givet"
            },
            {
              "icon": "",
              "label": "Ett RuntimeError, eftersom generatorer inte kan innehålla en return-sats"
            }
          ]
        },
        {
          "question": "Inuti en outer()-funktion, x = 1 är inställd, sedan gör en kapslad inner() nonlocal x; x += 1, och outer() anropar inner() innan den returnerar x. Vad returnerar outer()?",
          "options": [
            {
              "icon": "",
              "label": "1 — inner() opererar på sin egen lokala kopia av x, så ändringen kvarstår inte"
            },
            {
              "icon": "",
              "label": "Ett UnboundLocalError, eftersom x inte är deklarerat inuti inner() före nonlocal-satsen"
            },
            {
              "icon": "",
              "label": "Ett SyntaxError — nonlocal kan endast användas inuti klasser"
            },
            {
              "icon": "",
              "label": "2 — nonlocal låter inner() ändra outer-funktionens x istället för att skapa en ny lokal variabel"
            }
          ]
        },
        {
          "question": "d = {'a': 1, 'b': 2}. Vad returnerar d.get('c', 0), och lägger det till 'c' i ordlistan?",
          "options": [
            {
              "icon": "",
              "label": "0, och nej — get() returnerar standardvärdet utan att infoga nyckeln"
            },
            {
              "icon": "",
              "label": "0, och ja — get() infogar nyckeln med standardvärdet"
            },
            {
              "icon": "",
              "label": "KeyError, eftersom 'c' inte finns"
            },
            {
              "icon": "",
              "label": "Ingen, och ja — get() lägger alltid till saknade nycklar med ett None-värde"
            }
          ]
        },
        {
          "question": "t = (1, 2, [3, 4]). Kan du köra t[2].append(5), och kan du köra t[0] = 10?",
          "options": [
            {
              "icon": "",
              "label": "Båda fungerar — att kapsla en lista inuti en tuple gör hela tupeln förändring"
            },
            {
              "icon": "",
              "label": "Båda höjer TypeError — inget inuti en tuple kan någonsin ändras"
            },
            {
              "icon": "",
              "label": "t[2].append(5) höjer TypeError, men t[0] = 10 fungerar eftersom tuplar tillåter omtilldelning av sitt första element"
            },
            {
              "icon": "",
              "label": "t[2].append(5) fungerar eftersom listan inuti är förändring; t[0] = 10 höjer TypeError eftersom tupeln själv är oföränderlig"
            }
          ]
        },
        {
          "question": "Vilka av dessa returnerar en iterator som beräknar värden lat snarare än att bygga hela sekvensen i minnet på en gång: [x*x for x in range(1000000)] eller (x*x for x in range(1000000))?",
          "options": [
            {
              "icon": "",
              "label": "Den med parenteser, (x*x for x in range(1000000)) — det är ett generatoruttal"
            },
            {
              "icon": "",
              "label": "Den med hakparenteser — listomfattningar är alltid lat i Python 3"
            },
            {
              "icon": "",
              "label": "Båda är lata — den enda skillnaden är typen returnerad i slutet"
            },
            {
              "icon": "",
              "label": "Ingen — båda bygger den fulla sekvensen i minnet omedelbar"
            }
          ]
        },
        {
          "question": "Ett try-block dividerar med noll, except ZeroDivisionError-satsen skriver ut 'a', och en finally-sats skriver ut 'b'. Vad skrivs ut, och i vilken ordning?",
          "options": [
            {
              "icon": "",
              "label": "b sedan a — finally körs alltid före någon except-sats"
            },
            {
              "icon": "",
              "label": "a sedan b — den matchande except körs först, och finally körs alltid efteråt oavsett"
            },
            {
              "icon": "",
              "label": "Endast b — undantaget fångas inte faktiskt, så 'a' skrivs aldrig ut"
            },
            {
              "icon": "",
              "label": "Endast a — finally hoppas över när ett undantag redan har hanterats"
            }
          ]
        },
        {
          "question": "import copy; a = [[1, 2], [3, 4]]; b = copy.copy(a); b[0].append(99). Ändras a[0] också?",
          "options": [
            {
              "icon": "",
              "label": "Nej — copy.copy() duplicerar alltid kapslade objekt också"
            },
            {
              "icon": "",
              "label": "Nej — att lägga till b[0] skapar en helt ny lista för endast b[0]"
            },
            {
              "icon": "",
              "label": "Ja, men endast eftersom copy.copy() kallades utan deepcopy-argumentet"
            },
            {
              "icon": "",
              "label": "Ja — copy.copy() gör en grund kopia, så de kapslade listorna är fortfarande delade mellan a och b"
            }
          ]
        },
        {
          "question": "d = {'x': 1, 'y': 2}. Vad kontrollerar 'x' in d mot — nycklarna, värdena, eller båda?",
          "options": [
            {
              "icon": "",
              "label": "Värdena — `in` kontrollerar om 1 eller 2 motsvarar 'x'"
            },
            {
              "icon": "",
              "label": "Både nycklar och värden kontrolleras"
            },
            {
              "icon": "",
              "label": "Inget — `in` på en ordbok höjer alltid TypeError"
            },
            {
              "icon": "",
              "label": "Nycklarna — `in` på en ordbok testar medlemskap mellan dess nycklar, inte dess värden"
            }
          ]
        },
        {
          "question": "names = ['Al', 'Bo'] och scores = [10, 20]. Vad returnerar list(zip(names, scores))?",
          "options": [
            {
              "icon": "",
              "label": "[('Al', 'Bo'), (10, 20)]"
            },
            {
              "icon": "",
              "label": "['Al', 10, 'Bo', 20]"
            },
            {
              "icon": "",
              "label": "[('Al', 10), ('Bo', 20)]"
            },
            {
              "icon": "",
              "label": "Ett ValueError, eftersom zip kräver tre eller fler argument"
            }
          ]
        },
        {
          "question": "class Dog: tricks = [] håller en klasslistad lista, och add_trick lägger till self.tricks. d1 = Dog() och d2 = Dog() skapas båda, sedan körs d1.add_trick('sit'). Vad innehåller d2.tricks?",
          "options": [
            {
              "icon": "",
              "label": "[] — varje instans får sin egen oberoende kopia av tricks"
            },
            {
              "icon": "",
              "label": "['sit'] — tricks är en klasslistad lista delad av varje instans, så d1s ändring är synlig på d2 också"
            },
            {
              "icon": "",
              "label": "Ett TypeError — instanser kan inte lägga till en klassattribut"
            },
            {
              "icon": "",
              "label": "['sit'] endast efter d2 = Dog() körs igen"
            }
          ]
        },
        {
          "question": "class A har def greet(self): return 'A'. class B(A) har def greet(self): return 'B' + super().greet(). Vad returnerar B().greet()?",
          "options": [
            {
              "icon": "",
              "label": "'AB' — super() körs alltid före subklassens egen kod"
            },
            {
              "icon": "",
              "label": "'B' — super().greet() ignoreras eftersom B redan åsidosätter greet"
            },
            {
              "icon": "",
              "label": "'BA' — super().greet() anropar As metod och dess resultat läggs till 'B'"
            },
            {
              "icon": "",
              "label": "Ett AttributeError, eftersom A inte har någon greet-metod synlig för B"
            }
          ]
        },
        {
          "question": "class Point lagrar self.x i __init__ och definierar ingen andra metoder. p1 = Point(1) och p2 = Point(1). Vad returnerar p1 == p2 per standard?",
          "options": [
            {
              "icon": "",
              "label": "Sant — Python jämför alla matchande attribut per standard"
            },
            {
              "icon": "",
              "label": "Falskt — utan en anpassad __eq__, == faller tillbaka till identitetsjämförelse, och p1 och p2 är olika objekt"
            },
            {
              "icon": "",
              "label": "Sant, men endast eftersom båda objekten skapades med samma argument"
            },
            {
              "icon": "",
              "label": "Ett TypeError, eftersom Point inte definierar __eq__"
            }
          ]
        },
        {
          "question": "Vilken except-sats nedan kommer också att fånga ett ZeroDivisionError: except ArithmeticError, except ValueError, eller except KeyError?",
          "options": [
            {
              "icon": "",
              "label": "except ValueError — divisionsfel behandlas som ogiltiga värden"
            },
            {
              "icon": "",
              "label": "except KeyError — alla körningsfel inte knutna till en specifik typ faller tillbaka till KeyError"
            },
            {
              "icon": "",
              "label": "Ingen av dem — endast except ZeroDivisionError själv kan fånga det"
            },
            {
              "icon": "",
              "label": "except ArithmeticError — ZeroDivisionError är en underklass av ArithmeticError"
            }
          ]
        },
        {
          "question": "Du öppnar en fil med open('data.txt') as f: och ett undantag höjs vid läsning inuti blocket. Stängs filen fortfarande?",
          "options": [
            {
              "icon": "",
              "label": "Nej — filen förblir öppen eftersom blocket inte avslutades normalt"
            },
            {
              "icon": "",
              "label": "Endast om du också lägger till en finally-sats runt with-satsen"
            },
            {
              "icon": "",
              "label": "Ja — with-satsen anropar filens __exit__-metod, som stänger den, även om ett undantag inträffar inuti blocket"
            },
            {
              "icon": "",
              "label": "Det beror på undantagstypen — endast undantag som fångats någon annanstans utlöser rensning"
            }
          ]
        },
        {
          "question": "x = [3, 1, 2] och y = x.sort(). Vad håller y?",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 3] — sort() returnerar den nyligen sorterade listan"
            },
            {
              "icon": "",
              "label": "Ingen — list.sort() sorterar på plats och returnerar Ingen; x själv blir [1, 2, 3]"
            },
            {
              "icon": "",
              "label": "[3, 1, 2] — sort() returnerar den ursprungliga osorterade listan och ändrar bara xs interna ordning"
            },
            {
              "icon": "",
              "label": "Ett TypeError, eftersom sort() inte kan tilldelas till en variabel"
            }
          ]
        },
        {
          "question": "Vad händer när du kör 'Score: ' + 42?",
          "options": [
            {
              "icon": "",
              "label": "'Score: 42' — Python konverterar numret automatiskt inuti ett + uttryck"
            },
            {
              "icon": "",
              "label": "'Score: ' — numret ignoreras tyst"
            },
            {
              "icon": "",
              "label": "42 — strängen tvingas till ett tal och läggs till"
            },
            {
              "icon": "",
              "label": "TypeError — du kan inte sammanfoga en str och en int direkt, 42 måste konverteras med str() först"
            }
          ]
        },
        {
          "question": "Du behöver kontrollera om en lista som kallas results är tom. Vilken är det idiomatiska Python-sättet: if results == []: , if len(results) == 0: , eller if not results: ?",
          "options": [
            {
              "icon": "",
              "label": "if results == []: — det här är det enda pålitliga sättet att upptäcka en tom lista"
            },
            {
              "icon": "",
              "label": "if len(results) == 0: — det här krävs eftersom tomma listor är sanna i Python"
            },
            {
              "icon": "",
              "label": "Alla tre används aldrig i praktiken; standardtillvägagångssättet är if results is None:"
            },
            {
              "icon": "",
              "label": "if not results: — Python-idiom förlitar sig på sannvärde, och en tom lista är falsk"
            }
          ]
        }
      ],
      "optionOrderVersion": "92945565db6c55da"
    }
  }
}
