Core Types and Syntax
What each built-in type really is, when `is` and `==` disagree, and which operations copy versus alias. Interviewers open here because it explains most of Python's famous surprises.
part ofPythonoverview, primer and where to startread it →on this pageshowhide
explore
- Numbers and Booleans25 questions
- Integers, Bit Operations and bool4 questions
- Float Semantics and Pitfalls4 questions
- Decimal, Fraction and Exact Arithmetic5 questions
- Rounding Rules and round()4 questions
- Floor Division and Modulo4 questions
- Numeric Literals and int()4 questions
- Strings and Bytes22 questions
- str vs bytes and Encodings4 questions
- f-strings and the Format Mini-Language4 questions
- Immutability and Concatenation Cost3 questions
- t-string Template Literals3 questions
- Splitting, Stripping and Searching4 questions
- bytearray and memoryview4 questions
- Mutability, Identity and Copying20 questions
- Hashability and Default Arguments4 questions
- Identity vs Equality: is vs ==4 questions
- Shallow vs Deep Copy4 questions
- Interning and the Small-Integer Cache4 questions
- Augmented Assignment Surprises4 questions
- Sequence Semantics19 questions
- Slicing and Negative Indexing4 questions
- Unpacking and Starred Assignment4 questions
- Tuple Packing and Value Semantics4 questions
- Repetition and Shared References3 questions
- range Objects4 questions
- Truthiness and Comparisons18 questions
- Truthiness and Boolean Operators3 questions
- Chained Comparisons and Membership4 questions
- Rich Comparison and Ordering4 questions
- Defining __bool__ and __len__3 questions
- None and Sentinel Values4 questions
- Encoding and Normalization19 questions
- NFC, NFKC and casefold4 questions
- Codec Error Handlers4 questions
- UTF-8 Mode and Locale4 questions
- Universal Newline Translation4 questions
- BOM and utf-8-sig3 questions
questions
123 · 6 sectionsWhy use decimal.Decimal instead of float for currency amounts in Python?
basics
~20 sA float stores a binary fraction, so an amount written as 0.10 is not held exactly and the tiny errors accumulate as you add. decimal.Decimal stores base-10 digits, so 0.10 built from the string '0.10' is exact and money totals stay exact.
Why does 0.1 + 0.2 == 0.3 evaluate to False in Python?
basics
~20 sPython's float is IEEE-754 binary64, which stores exactly only fractions with a power-of-two denominator. 0.1, 0.2 and 0.3 each become nearby approximations, and the sum of the first two lands one step above the stored 0.3.
Why can a Python int hold 2 ** 200 without overflowing, and what does that cost?
basics
~20 sPython 3 has one integer type and it is arbitrary precision: CPython stores a sign plus a variable-length array of digits and grows it on demand, so arithmetic never wraps. You pay in memory and in math that is slower than machine words.
What do -7 // 2 and -7 % 2 evaluate to in Python, and why?
basics
~20 s-7 // 2 is -4 and -7 % 2 is 1. Python floors the quotient toward negative infinity instead of truncating toward zero, so the remainder always carries the sign of the divisor rather than the dividend.
Why does int('3.0') raise ValueError while int(3.0) returns 3?
basics
~20 sint() parses text with the integer grammar only, so the dot in '3.0' makes it a ValueError. Given a float object it converts numerically, truncating toward zero. For decimal text, call float() first and then int().
What is the difference between Python's str and bytes types?
basics
~20 sstr holds Unicode code points, meaning text; bytes holds raw octets valued 0 to 255, meaning data. Python 3 never converts between them implicitly: str.encode() produces bytes and bytes.decode() produces text, and each names an encoding.
What is the difference between an f-string, str.format and %-formatting in Python?
basics
~20 sAll three build a str. An f-string is a literal whose expressions are evaluated where it is written, so it cannot be stored as a reusable template; str.format and the % operator format a template string supplied at call time.
Why does calling s.upper() on a Python string leave s unchanged?
basics
~20 sPython str objects are immutable, so no method can change one in place. str.upper() builds and returns a brand-new string and leaves the original untouched, which is why you must assign the result: s = s.upper().
What is the difference between bytes and bytearray in Python?
basics
~20 sbytes is an immutable sequence of octets; bytearray is the mutable version you can append to and edit in place. Only bytes is hashable, so only bytes works as a dict key or set member.
Why doesn't 'scores.csv'.strip('.csv') simply remove the file extension?
basics
~10 sstr.strip takes a set of characters, not a suffix. It peels any of '.', 'c', 's' or 'v' off both ends, so 'scores.csv'.strip('.csv') returns 'ore'. Use str.removesuffix('.csv'), added in Python 3.9.
Why does `b = a` on a Python list leave both names pointing at one object?
basics
~20 sAssignment never copies in Python; it binds a second name to the same object. After b = a both names label one list, so b.append(4) is visible through a. Duplicate explicitly with a.copy(), a[:] or list(a).
What is the difference between `is` and `==` in Python?
basics
~20 sis asks whether two names are bound to one and the same object, the identity test behind id(). == asks whether the objects compare equal, dispatching to eq. Compare values with ==; reserve is for None, True, False and sentinels.
Why does `lst += [4]` change the list other names see, but `n += 1` does not?
basics
~20 s+= on a list calls list.__iadd__, which extends that same list object in place, so every name bound to it sees the new items. An int is immutable: n += 1 builds a new int and rebinds only the name n.
Which of Python's built-in types are immutable, and which can be changed in place?
basics
~20 sint, float, bool, str, bytes, tuple and frozenset are immutable: every apparent change builds a new object. list, dict, set and bytearray are mutable and can be modified in place through any name that refers to them.
Why does `dict.copy()` leave nested lists shared with the original dict?
basics
~20 sdict.copy() is shallow: it builds a new dict whose values are the very same objects as the original's. Replacing a key in the copy is independent, but mutating a nested list is seen by both dicts. copy.deepcopy duplicates the nested objects too.
How does a Python range object differ from a list of the same numbers?
basics
~20 sA range object stores only start, stop and step, so it occupies the same few dozen bytes whether it spans ten values or a billion. A list of the same numbers materializes every int in memory.
Why does `[[0]*3]*3` change a whole column when you assign one cell?
basics
~10 s* repeats references, not objects. [[0]*3]*3 stores one inner list three times, so mutating g[0][0] is visible through every row. Build the rows separately with [[0]*3 for _ in range(3)].
Why does the Python slice items[1:4] return three elements, not four?
basics
~20 sPython slices are half-open: the start index is included and the stop index is excluded. So items[1:4] yields positions 1, 2 and 3, and with the default step the length is simply stop minus start.
Why is (5) just an int in Python while (5,) is a one-element tuple?
basics
~20 sIn Python the comma builds a tuple, not the parentheses. (5) is the integer 5 inside redundant grouping brackets, while the trailing comma in (5,) makes a one-element tuple. Empty () is the only exception.
What does `a, b = b, a` do in Python, and why is no temporary variable needed?
basics
~20 sPython evaluates the entire right-hand side first, building the pair (b, a), then binds the targets on the left one at a time. Both original values are captured before either name is rebound, so no manual temporary is needed.
What does `a < b < c` mean in Python, and how many times is `b` evaluated?
basics
~10 sPython expands a < b < c into a < b and b < c, but evaluates the middle expression exactly once. If the first comparison is false, the second comparison is never performed.
Why does `3 < 'apple'` raise TypeError in Python 3 when Python 2 ordered them?
basics
~10 sPython 3 removed the default ordering between unrelated types. The int's less-than returns NotImplemented for a str, the reflected str greater-than returns NotImplemented too, and with no fallback left the interpreter raises TypeError.
In Python, how does `if obj:` decide truthiness for an instance of a custom class?
basics
~20 sif obj: calls bool(obj), which looks for __bool__ on the object's type. If there is none, Python falls back to __len__, where a length of 0 means false. With neither defined, every instance is true.
Why check `if timeout is None:` instead of `if not timeout:` for an optional argument?
basics
~20 sif not timeout: is true for 0, 0.0, '' and [] as well as None, so it silently discards values the caller passed on purpose. is None asks only one question: was the argument omitted?
Which built-in Python values are falsy inside an `if` statement?
basics
~20 sFalsy built-ins are None, False, zero of any numeric type (0, 0.0, 0j) and every empty container: '', b'', [], (), {}, set(), range(0). Everything else, including the string '0' and the list [0], is truthy.
What is the difference between Python's 'utf-8' and 'utf-8-sig' codecs?
basics
~20 sPython's utf-8 codec treats a leading byte-order mark as an ordinary character, so it decodes to U+FEFF at the front of the string. The utf-8-sig codec strips one leading mark on read and always writes one on encode.
What does the errors= argument to bytes.decode() control in Python?
basics
~20 sIt chooses what happens when the input bytes are not valid for the codec. 'strict' is the default and raises UnicodeDecodeError; 'ignore' deletes the bad bytes; 'replace' substitutes U+FFFD; 'backslashreplace' writes an escape for each bad byte.
What encoding does Python's open() use when you do not pass encoding=?
basics
~20 sA text-mode open() with no encoding= uses the locale encoding that locale.getencoding() reports: usually UTF-8 on Linux and macOS, but the ANSI code page on Windows. It is not guaranteed to be UTF-8, so pass encoding= explicitly.
Why can two Python strings that look identical compare unequal with ==?
basics
~20 sBecause == compares code points, not shapes. An accented letter can be one precomposed code point or a base letter plus a combining mark; both render the same but differ. unicodedata.normalize('NFC', s) folds them to one form before comparing.
Why must a file handed to Python's csv.writer be opened with newline=''?
basics
~20 sBecause csv.writer emits its own '\r\n' terminator. Left at newline=None, text mode translates the '\n' inside it again — on Windows that yields '\r\r\n' and a blank row between every record. newline='' switches that translation off.