November 30: Built-in Constants, Types, Exceptions
After yesterday's built-in functions, today's entry in the traversal of the Python Standard Library docs takes us to the built-in constants, types and exceptions.
The things I learned or found most interesting in this post:
- I keep forgetting that
string.casefold()for case-insensitive comparison, and
expandtab()to replace tabs with spaces, without reverse operation, mwahaha.
- You can assign to list slices (duh), and that includes stepped slices (
- I played a bit with
memoryview, which lets you access and manipulate
bytearraysdirectly by exposing the raw integers.
- I didn't know that if you use
my_set.union()you can actually use any iterable as argument (as opposed to
my_set | other_setwhere
other_setreally needs to be a set)
Most constants live in modules, but some are in the built-in
None are the important ones.
...) is mostly important to show
up people who don't know about it.
__debug__ tells you if you can use assert statements.
NotImplemented is a
constant that, when returned from arithmetic special methods like
__add__(), will lead to
NotImplementedError to be
raised. Don't confuse those. (Also,
license to print stuff, if you're into
All exceptions derive from
BaseException. Built-in exceptions usually have a value (string or tuple) that explains
what exactly is going on, passed to the constructor. You can use either the built-in classes or subclass them.
When raising new exceptions in an exception context, remember to use
raise from to provide the previous context.
Then you get all sorts of exception classes:
Exception, of course,
ArithmeticError subclasses (
LookupError subclasses (
Key), and various useful stuff
TypeError, the dread
NotImplementedError, if you're happy and you
OSErrors are a bit particular about their parameters and there are tons of subclasses for all
sorts of OS oops neds.
Warnings (messages typically written to stderr) use exception subclasses as categories.
Booleans, truth, comparison
Every object can be tested for its truth value. Objects are assumed to be true unless their
__len__() returns zero. All operations with boolean results return 0/1/
False, except for
which return their last decisive operand.
x < y < z are evaluated like
x < y and y < z, except that
y is evaluated only one. You can
implement comparison sufficiently by implementing
__eq__(), though you are of course free to implement
__ge__(). You cannot override
is not behaviour. For
We get floats, integers and complex numbers by default, and then other numeric types defined in modules, like
fractions.Fraction. We get tons of operations: don't forget that next to the standard, there are
divmod. On integers, you get bitwise operations (
bit_length() and byte
conversion. On floats, you get things like
as_integer_ratio() (for hilarious results),
is_integer(), and hex
Iterators and generators
Iterator types are the best magic. The
__iter__() method on the iterable returns an iterator (and on the iterator, for
ease of use). The iterator has a
__next__() method that returns the next element or raises a
Generators do this for you by using the
yield keyword in their function body.
Sequence types are lists, tuples, and range objects. Shared operations are containment operators (
addition (concatenation), multiplication (repetition), indexed access, slicing, length checks, min and max operations,
equality and particularly
Immutable sequence types are mostly different by actually implementing a hash function, so you can use them as
dictionary keys, for example. Mutable sequence types support assignment to items, or to slices, even stepped slices.
They also support
reverse(). Lists have a
(but you can also use the
sorted built-in). Ranges are immutable sequences mostly used for looping. Just like
slices, they take a start, and end and a step. Range values are good because they are memory efficient.
I'm offended by the fact that the three main ways to write strings are single quotes, double quotes and triple quotes, but the names don't correspond to the amount of characters used aaaah.
String methods are manifold, helpful, and easy to forget. I'm listing them here in an effort to forget less of them:
index(substring)find occurrences (plus
split()(remember to use maxsplit!),
casefold()for case insensitive matching
New in 3.9:
Python has at least three kinds of string formatting, oh joy. I'm not going into the details here, because that deserves its own post.
byte (immutable) and
bytearray (mutable) to manipulate binary data, for instance by using
interact with memory representations of objects directly.
bytes support all the same methods that strings do, only
always limited to ASCII characters. Shove bytes into a
memoryview to be able to access them individually, and inspect
the underlying memory layout.
frozenset are great! Methods include
^, plus the same again for assignments. Note that things like
union() can take any
| is restricted to actual sets.
If you want more like this, wait until we talk about the collections module.
dictview, which is connected to the dictionary and updates when it changes.
New in 3.9: You can merge dictionaries with
Context managers are amazing and cool! Use them with
with statement, implement the
If you want to build context managers, use the
contextlib for standard library context managers.
Other built-in types include modules, classes, functions, methods (bound methods in particular), code objects, type objects, ...