Python Module 2
Values, variables, numbers and strings interview questions
Interview questions on values, variables, numbers and strings: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
What is a variable in Python, and what does an assignment such as x = 5 actually do?
Answered in the lesson Variables, objects and names in Python
-
Fresher
What is the difference between / and // in Python?
Answered in the lesson Integers, floats and arithmetic operators
-
Fresher
Why is 0.1 + 0.2 not equal to 0.3 in Python?
Answered in the lesson Floating-point surprises and how to handle them
-
Fresher
What is the difference between == and is in Python?
Answered in the lesson Booleans, None, truthiness and comparisons
-
Fresher
What is the value of -3 ** 2 in Python, and why?
-
Fresher
What does it mean that Python strings are immutable?
Answered in the lesson Strings: literals, indexing and slicing
-
Fresher
What is the difference between find() and index() on a string?
Answered in the lesson Essential string methods for cleaning text
-
Fresher
What are f-strings, and why are they preferred to % formatting and str.format()?
Answered in the lesson f-strings and the format mini-language
-
Fresher
What does input() return, and how do you read a number with it safely?
Answered in the lesson Input and output: print(), input() and stdin
-
Fresher
How do you convert a string to an integer in Python, and what can go wrong?
Answered in the lesson Type conversion, number bases and bitwise operators
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
A data script that worked for months now stops with TypeError: 'str' object is not callable, on a line that calls str(amount). The day before, a change added str = row["label"] near the top of the file. Diagnose the failure, fix it, and explain how you would stop changes like this from being merged.
- What it tests
- The order in which Python looks up names, reading the error message, renaming instead of working around, and linters and review that prevent shadowed built-ins.
- First step
- Read the message literally: the object being called is a str, so the name str in str(amount) no longer refers to the built-in type. Search the file for an assignment to str, and the new line str = row["label"] is the cause.
- Follow-ups
-
- Why did the line that assigned str raise no error?
- Would moving the assignment into a function fix the script?
- Which tools catch this before the code runs?
From the lesson Variables, objects and names in Python
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A service is being ported from Java to Python. It puts events into one-minute buckets with offset / 60 and works out the second within the bucket with offset % 60, where offset is in seconds and can be negative. After the port, the numbers for events before the reference time differ. Explain why, and decide which behaviour each calculation needs.
- What it tests
- Floor division against truncation, the sign of the remainder, and choosing the rounding a calculation needs instead of copying the old language's rule.
- First step
- Work one negative case in both languages. For offset = -1, Java gives -1 / 60 = 0 and -1 % 60 = -1, while Python gives -1 // 60 = -1 and -1 % 60 = 59: Java truncates towards zero, and Python floors, with a remainder that takes the sign of the divisor.
- Follow-ups
-
- Which of the two is right for time buckets?
- How do you get Java's results in Python when another system depends on them?
- What would you test before switching over?
From the lesson Integers, floats and arithmetic operators
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
An API reads a JSON body and takes the quantity with int(body["quantity"]). A client sends a quantity of 50,000 digits. What happens in CPython 3.14, why does CPython behave that way, and how should the endpoint validate the field so that neither huge nor malformed values reach the business logic?
- What it tests
- The integer string conversion limit and the attack it blocks, the cost of conversion, and validating size and range at the boundary instead of trusting a default.
- First step
- Say what the call does: int() of a 50,000-digit string raises ValueError, because CPython refuses decimal conversions of more than 4,300 digits by default. If the quantity is a JSON number rather than a string, json.loads() raises the same ValueError while parsing, before the handler sees the field at all.
- Follow-ups
-
- Why not raise the limit with sys.set_int_max_str_digits(0)?
- What does a conversion cost when the limit is off?
- Where should the check live, and what should the client see?
From the lesson Integers, floats and arithmetic operators
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Mid to senior
A billing service keeps amounts as floats, in rupees. At the end of the month its total for a merchant differs from the bank's statement by a paisa or two. Find the likely causes, and design the fix for how amounts are stored, added and rounded.
- What it tests
- Where floats lose decimal amounts (parsing, conversion, rounding rules), how big each effect really is, and a design with exact types and one written rounding rule.
- First step
- List where a float can lose a paisa: amounts parsed from text into floats that cannot hold them exactly, then conversions such as int(amount * 100), which turns 19.99 into 1998 paise, and rounding applied at different points than the bank applies it. Measure each before blaming the sum.
- Follow-ups
-
- Should the service keep paise as ints or rupees as Decimal?
- Which rounding rule should an 18 % tax use, and where is it applied?
- How do you prove the fix against past statements?
From the lesson Floating-point surprises and how to handle them
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A unit test asserts compute_ratio() == 0.3. It passes on one laptop, fails in CI after a dependency upgrade, and the failure message shows two values that look the same. Explain what is going on, and rewrite the test so that it checks what matters.
- What it tests
- Why == on computed floats is fragile, how printing hides the last bits, and choosing relative and absolute tolerances for a test.
- First step
- Print both values with repr() or Decimal instead of a formatted string. Two floats that both show 0.3 to fifteen digits can still differ in their last bit, and any change in the order of the operations, such as a library that adds in a different order, moves that bit.
- Follow-ups
-
- How do you choose rel_tol and abs_tol for this test?
- When is an exact float comparison right in a test?
- What does pytest.approx do by default?
From the lesson Floating-point surprises and how to handle them
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A service reads its timeout with timeout = config.get("timeout") or 30. An operator sets "timeout": 0 to mean no timeout at all, yet requests still stop after 30 seconds. Explain the bug, fix it, and say how you would find the same mistake elsewhere in the code base.
- What it tests
- How or picks its result, falsy values that are real answers, explicit tests for missing values, and finding a pattern across a code base.
- First step
- Evaluate the expression with the operator's value: config.get("timeout") returns 0, 0 is falsy, so or returns its right operand, 30. The 0 never reaches the code that would switch the timeout off.
- Follow-ups
-
- Why not write if timeout: to check whether a timeout was set?
- How would you write the lookup if None can also be a valid setting?
- How do you find this pattern across a large code base?
From the lesson Booleans, None, truthiness and comparisons
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
In a code review you find if record == None: in a data pipeline. The author says it works in every test. Explain why PEP 8 asks for is None instead, and describe values for which == None gives a wrong or surprising result.
- What it tests
- How == hands the question to the objects' own equality methods, why is cannot be redefined, and real values for which == None misleads or fails.
- First step
- Say what each operator asks. == lets the objects' equality methods decide, so any class can choose what record == None means; is asks whether record is the one None object, which no class can change.
- Follow-ups
-
- What happens with a NumPy array in place of record?
- Is there any cost to is None compared with == None?
- When is it right to compare with == when one side might be None?
From the lesson Booleans, None, truthiness and comparisons
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A nightly job checks 2 million log lines against 200,000 blocked IP addresses with if ip in blocked:, where blocked is a list read from a file. The job takes about half an hour. Explain why, estimate the cost, fix it, and say what the fix itself costs.
- What it tests
- How in works on a list and on a set, estimating cost from the sizes, and weighing the time saved against the memory a set needs.
- First step
- Point at the list: in reads it item by item, so every address that is not blocked is compared with all 200,000 entries before the answer is no. With 2 million lines that is up to 400 billion comparisons.
- Follow-ups
-
- How much memory does the set add?
- What if the blocklist changes while the job runs?
- When would you keep a list, or use something other than a set?
From the lesson Operators, precedence and the walrus
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A report should list large sales from two regions, written as if region == "south" or region == "west" and amount > 10_000:. A sale of 500 from the south appears in it. Explain why, fix the condition, and say how you would keep conditions like this readable and tested.
- What it tests
- and binding more tightly than or, rewriting the condition with brackets or a membership test, and testing a condition with a table of cases.
- First step
- Add the brackets Python adds: and binds more tightly than or, so the condition is region == "south" or (region == "west" and amount > 10_000). Every sale from the south passes, whatever its amount.
- Follow-ups
-
- How would you write the condition so that nobody can misread it?
- Which test cases would have caught the bug?
- Would a linter or a type checker catch it?
From the lesson Operators, precedence and the walrus
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A nightly job builds a 200,000-line report with report += line inside a loop. On busy days it runs far longer than the extra lines suggest, yet a teammate says the same code is fast on their laptop. Explain the cost, why it can hide, and rewrite the loop.
- What it tests
- Why repeated concatenation of an immutable string costs time that grows with the square of its length, why CPython's in-place shortcut is fragile, and building text with join() or io.StringIO.
- First step
- Count what the loop copies. Each += makes a new string holding everything so far plus one line, so n lines of m characters copy about m times n squared over 2 characters in total, while one join() at the end copies about m times n.
- Follow-ups
-
- Why might the same loop look fast in a quick test?
- When would you use io.StringIO instead of a list and join()?
- How would you prove the fix on the real data?
From the lesson Strings: literals, indexing and slicing
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A profile page cuts display names to 20 characters with name[:20]. People with Hindi names report that the last letter on screen is broken. Explain what goes wrong, cut the text safely, and say how you would test it.
- What it tests
- Code points against the letters people see, vowel signs and the virama, a safe place to cut with the standard library, and tests built from real names.
- First step
- Look at what the slice counts: 20 code points, not 20 letters. In Devanagari a vowel sign or a virama is a code point of its own that belongs with the letter before it, so a cut between them leaves a letter without its sign, or half of a joined letter.
- Follow-ups
-
- Would cutting by bytes, to fit a database column, help?
- How can you cut safely with the standard library alone?
- Which names would you put in the tests?
From the lesson Strings: literals, indexing and slicing
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 4 minutes
-
Fresher to mid
A sign-up form stores email addresses exactly as typed. Months later one person has two accounts, one for " Asha.Rao@Example.com" and one for "asha.rao@example.com". Explain how that happened, how you would compare addresses from now on, and what you would do about the accounts that already exist.
- What it tests
- Normalising text for comparison with strip() and casefold(), keeping the stored value apart from the comparison key, the case rules of email addresses, and a safe migration.
- First step
- Compare the two strings as the database does: one starts with a space and their capitals differ, so == and a unique index both see two different addresses, although a mail server delivers both to the same person.
- Follow-ups
-
- Why not lower-case the address and store only that?
- Should the key also drop dots or a +tag from the part before the @?
- How do you fix the accounts that already exist?
From the lesson Essential string methods for cleaning text
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
An import script reads a CSV export with fields = line.strip().split(","). It works until a customer's address, saved in quotes as "Flat 4, MG Road", shifts every later column by one. Explain the bug, fix it, and say how you would test the import.
- What it tests
- Why split(",") cannot read CSV, how quoting works in CSV, the csv module and newline="", and tests with quoted and multi-line fields.
- First step
- Split the failing line by hand: split(",") cuts at every comma, the one inside the quotes too, so the address becomes two fields with the quotes still on them, and every field after it moves one place to the right.
- Follow-ups
-
- What does newline="" do when the file is opened?
- How should the import notice a row with the wrong number of fields?
- What changes when the export is several gigabytes?
From the lesson Essential string methods for cleaning text
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
An invoice prints each line with f"{amount:.2f}" and the total with f"{total:.2f}", where total adds the unrounded line amounts. Three items at 84.75 rupees plus 18 % GST each show 100.00, but the total shows 300.01. Explain both numbers and fix the invoice.
- What it tests
- That formatting rounds only what is shown, how floats round a value such as 100.005, one rounding rule applied once, and exact amounts with integer paise or Decimal.
- First step
- Separate the stored value from the text. 84.75 times 1.18 is 100.005 in decimal, but the float holds the nearest binary value, a little below it, so .2f writes 100.00; the total adds three unrounded floats, about 300.015, and rounds only that sum.
- Follow-ups
-
- Why does f"{x:.2f}" not give 100.01 here?
- Should the tax be rounded per line or on the total?
- How would you test that every invoice adds up?
From the lesson f-strings and the format mini-language
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A service calls logger.debug(f"order={order!r}") on every request. In production the level is INFO, so no debug line is ever written, yet profiling shows real time spent in these calls. Explain why, fix it, and say when an f-string in a log call is still fine.
- What it tests
- Eager evaluation of f-strings, the logging module's deferred % formatting, isEnabledFor() for costly arguments, and what log tools do with a message template.
- First step
- Look at when each part runs. The f-string is evaluated before logger.debug() is even called, so repr(order) builds its text on every request; only then does the logger see that DEBUG is off and throw the finished string away.
- Follow-ups
-
- What does logger.debug("order=%r", order) change?
- When is isEnabledFor() needed as well?
- Is an f-string in a log call ever the better choice?
From the lesson f-strings and the format mini-language
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A solution reads a million numbers, one per line, with int(input()) in a loop. It passes the small tests but runs out of time on the large one. Explain where the time goes, rewrite the reading, and say how you would measure the gain without the judge.
- What it tests
- The work each input() call does besides reading, reading input in one call or with sys.stdin.readline(), writing output in one go, and timing both versions on a generated input.
- First step
- Look at what runs a million times. Each input() call looks up the standard streams, flushes standard error and standard output, and checks whether it is talking to a terminal before it reads its line, and the loop pays that a million times over.
- Follow-ups
-
- How much faster is sys.stdin.readline(), and why?
- What about printing a million lines of output?
- How do you measure it on your own machine?
From the lesson Input and output: print(), input() and stdin
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A calculator program reads each line with eval(input()), so that users can type 2 + 3 * 4. Explain why that is unsafe, and replace it with code that accepts arithmetic on numbers and nothing else.
- What it tests
- Why eval() runs any expression, why ast.literal_eval() is not enough for arithmetic, and a small evaluator over Python's own parse tree, with limits and tests that prove the fix.
- First step
- Say what eval() does: it runs the text as a Python expression with all the powers of the program, so a line can call any function the program could call, not only add numbers.
- Follow-ups
-
- Why not use ast.literal_eval() instead?
- Which limits does the safe version need?
- How would you test that the fix holds?
From the lesson Input and output: print(), input() and stdin
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A service reads its debug switch with DEBUG = bool(os.environ.get("APP_DEBUG", "")). Operators set APP_DEBUG=0, and later APP_DEBUG=false, to switch debug logging off, but it stays on. Explain why, fix it, and say how you would stop the same bug in the other settings.
- What it tests
- Truthiness of strings, reading yes-or-no settings explicitly, refusing unknown values instead of guessing, and keeping the parsing of every setting in one tested place.
- First step
- Evaluate it with the operator's value: os.environ.get() returns the string "0", and bool() of any non-empty string is True, so "0" and "false" both switch debugging on. Only a missing or empty variable gives False.
- Follow-ups
-
- Which words should count as on and as off?
- What should happen for a value such as "ture" or "2"?
- How do you find the same bug in the rest of the code?
From the lesson Type conversion, number bases and bitwise operators
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A function turns colour codes such as "#1E90FF" into red, green and blue with int(code[1:3]), int(code[3:5]) and int(code[5:7]). Some codes crash with ValueError, and others give wrong colours with no error at all. Explain both, fix the function, and test it.
- What it tests
- Reading digits in the right base, why a wrong base can fail silently, validating the whole format before converting, the three-digit shorthand, and tests that catch silent errors.
- First step
- Look at what int() does without a base: it reads decimal digits. "1E" holds a letter, so it raises ValueError, but "90" is valid decimal and becomes 90 instead of the hexadecimal 144, with no error at all.
- Follow-ups
-
- Which inputs should the function accept?
- How do you write tests that a silent error cannot pass?
- What changes for codes with an alpha part, such as "#1E90FF80"?
From the lesson Type conversion, number bases and bitwise operators
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes