Python has NaN float value and it's a rule-breaking thing:
Be careful. Use
import math
sorted([5.0, math.nan, 10.0, 0.0])
# [5.0, nan, 0.0, 10.0]
3 < math.nan
# False
3 > math.nan
# False
min(3, math.nan)
# 3
min(math.nan, 3)
# nan
Be careful. Use
math.isnan
to check if a value is NaN.Some functional languages, like Elixir, have in the standard library a huge collection of functions to work with lazy enumerables (in Python, we name them iterators). In Python, this role is on itertools. However,
All these examples and much more can be imported from more-itertools third-party library.
itertools
is a relatively small collection of such functions, it contains only most important and basic ones (maybe, a bit of junk, but so). The documentation has Itertools Recipes with some useful functions. A few examples:def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
def prepend(value, iterator):
"Prepend a single value in front of an iterator"
# prepend(1, [2, 3, 4]) -> 1 2 3 4
return chain([value], iterator)
def tail(n, iterable):
"Return an iterator over the last n items"
# tail(3, 'ABCDEFG') --> E F G
return iter(collections.deque(iterable, maxlen=n))
def nth(iterable, n, default=None):
"Returns the nth item or a default value"
return next(islice(iterable, n, None), default)
All these examples and much more can be imported from more-itertools third-party library.
What are static type checkers you ever tried?
Anonymous Poll
49%
mypy
4%
pyre
5%
pytype
4%
pyright
1%
pyanalyze
47%
None of the above
What are static type checkers you actively use?
Anonymous Poll
39%
mypy
1%
pyre
3%
pytype
2%
pyright
1%
pyanalyze
57%
None of the above
There is a built-in function
format
that basically just calls __format__
method of the passed argument type with passed spec. It is used in str.format
as well.class A:
def __format__(self, spec):
return spec
format(A(), 'oh hi mark')
# 'oh hi mark'
'{:oh hi mark}'.format(A())
# 'oh hi mark'
Every class is an instance of its metaclass. The default metaclass is
However, class and instance are both an instance of
This is because
type
. You can use this knowledge to check if something is a class or is an instance:class A: pass
isinstance(A, type) # True
isinstance(A(), type) # False
However, class and instance are both an instance of
object
!isinstance(A(), object) # True
isinstance(A, object) # True
This is because
type
an instance of object
and subclass of object
at the same time, and object
is an instance of type
and has no parent classes.isinstance(type, object) # True
issubclass(type, object) # True
type(type) # type
type(object) # type
type.__mro__ # (type, object)
object.__mro__ # (object,)
What are web frameworks you use?
Anonymous Poll
28%
aiohttp
2%
bottle
50%
django
17%
fastapi / starlette
44%
flask
2%
pyramid
6%
tornado
8%
Other
11%
None
Everything is an object, including functions, lambdas, and generators:
Generators have no
g = (i for i in [])
def f(): pass
type(g).__mro__ # (generator, object)
type(f).__mro__ # (function, object)
type(lambda:0).__mro__ # (function, object)
Generators have no
__dict__
but functions do!def count(f):
def w():
w.calls += 1
return f()
# let's store an attribute in the function!
w.calls = 0
return w
@count
def f():
return 'hello'
f()
f()
f.calls
# 2
Python caches every imported module is
You can reload any module with
sys.modules
:import sys
import typing
sys.modules['typing']
# <module 'typing' from '/usr/local/lib/python3.7/typing.py'>
len(sys.modules)
# 637
You can reload any module with
importlib.reload
to force it to be executed again. Be careful, though, since every object from the module will be recreated, you can break all isinstance
checks and have hard times with debugging it.old_list = typing.List
old_list is typing.List
# True
importlib.reload(typing)
old_list is typing.List
# False
Module numbers was introduced by PEP-3141 in Python 2.6. It implements the numbers hierarchy, inspired by Scheme:
They are ABC classes, so they can be used in
+
+ fractions.Fraction is
+
+
+ decimal.Decimal is
In theory,
The most fun thing about
Number :> Complex :> Real :> Rational :> Integral
They are ABC classes, so they can be used in
isinstance
checks:import numbers
isinstance(1, numbers.Integral)
# True
isinstance(1, numbers.Real)
# True
isinstance(1.1, numbers.Integral)
# False
+
int
is Integral
.+ fractions.Fraction is
Rational
.+
float
is Real
.+
complex
is Complex
(wow!)+ decimal.Decimal is
Number
.In theory,
Decimal
should be Real
but it's not because Decimal
doesn't interoperate with float
:Decimal(1) + 1.1
# TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'
The most fun thing about
numbers
is that it's not supported by mypy.types.SimpleNamespace is a way to make a
However, values from SimpleNamespace can't be accessed by getitem anymore because "There should be only one obvious way to do it":
dict
with access by attributes:from types import SimpleNamespace
sn = SimpleNamespace(a=1, b=2)
sn.a
# 1
sn.c
# AttributeError: ...
However, values from SimpleNamespace can't be accessed by getitem anymore because "There should be only one obvious way to do it":
sn['a']
# TypeError: 'types.SimpleNamespace' object is not subscriptable
How many ways you know how to convert
Can you beat it?
int
to str
? Let's try! Note that complications of the same method don't count.n = 13
n.__str__() # 1
str(n) # 2
'{}'.format(n) # 3
'%i' % n # 4
f'{n}' # 5
format(n, 'd') # 6
from string import Template
Template('$n').substitute(n=n) # 7
# similar to other methods:
n.__repr__()
repr(n)
str.format('{}', n)
n.__format__('d')
Can you beat it?
The point of the post above was that for some simple tasks there are many ways to do it (and some ways are good only in some cases). Also, the number of possible solutions grows as the language evolves. Another good example is concatenation. You can join 2 strings with f-strings,
Our amazing subscribers decided to take the challenge. Below are some not suitable for work but fan solutions how to convert int to str.
@dedefer:
Evgeny:
If you're going to use solutions below on the production, keep in mind that it doesn't work with negative numbers.
@oayunin:
A similar solution from @apatrushev:
A similar solution with lambdas from @antonboom:
One more from @oayunin:
@orsinium:
@maxvyaznikov:
str.format
, str.join
, +
, and so on. Thinking about these ways, even not suitable for daily usage, helps better language understanding.Our amazing subscribers decided to take the challenge. Below are some not suitable for work but fan solutions how to convert int to str.
@dedefer:
import io
with io.StringIO() as f:
print(n, end='', file=f)
n_str = f.getvalue()
Evgeny:
import ctypes
ctypes.cdll.LoadLibrary('libc.so.6').printf(b'%d', n)
If you're going to use solutions below on the production, keep in mind that it doesn't work with negative numbers.
@oayunin:
from math import log10
''.join(['0123456789'[(n // 10 ** i) % 10] for i in range(int(log10(n)), -1, -1)])
A similar solution from @apatrushev:
''.join(chr(t + 48) for t in (n // 10**x % 10 for x in reversed(range(int(math.log(n,10)) + 1))) if t)
A similar solution with lambdas from @antonboom:
(lambda n:
''.join(
chr(ord('0') + (n // (10**i)) % 10)
for i in range(math.ceil(math.log(n, 10)) - 1, -1, -1)
)
)(n)
One more from @oayunin:
from subprocess import check_output
with open('/tmp/tmp.txt', 'w') as f:
for x in range(n):
f.write(' ')
check_output(['wc', '-c', '/tmp/tmp.txt']).decode().split()[0]
@orsinium:
import sys
import subprocess
cmd = [sys.executable, '-c', 'print(len("' + '*' * n + '"))']
subprocess.run(cmd, capture_output=True).stdout.strip().decode()
@maxvyaznikov:
chars = []
while n > 0:
digit = n % 10
n = int(n / 10)
chars.append(chr(ord('0') + digit))
print(''.join(chars[::-1]))
Context manager contextlib.nullcontext is helpful when a block of code not always should be executed in a context.
A good example is a function that works with a database. If a session is passed, the function will use it. Otherwise, it creates a new session, and does it in a context to guarantee fallback logic to be executed:
Another example is optional suppressing errors:
It was added in Python 3.7. For earlier Python versions DIY:
Another option is to use ExitStack.
A good example is a function that works with a database. If a session is passed, the function will use it. Otherwise, it creates a new session, and does it in a context to guarantee fallback logic to be executed:
from contextlib import nullcontext
def get_user(id, session=None):
if session:
context = nullcontext(session)
else:
context = create_session()
with context as session:
...
Another example is optional suppressing errors:
from contextlib import suppress
def do_something(silent=False):
if silent:
context = suppress(FileNotFoundError)
else:
context = nullcontext()
with context:
...
It was added in Python 3.7. For earlier Python versions DIY:
from contextlib import contextmanager
@contextmanager
def nullcontext(value=None):
yield value
Another option is to use ExitStack.
The module enum provides a way to build an enumerable class. It is a class with a predefined list of instances, and every instance is bound to a unique constant value.
from colorsys import rgb_to_hls
from enum import Enum
class Color(Enum):
RED = (1, 0, 0)
GREEN = (0, 1, 0)
BLUE = (0, 0, 1)
@property
def hls(self):
return rgb_to_hls(*self.value)
Color
# <enum 'Color'>
Color.RED
# <Color.RED: (1, 0, 0)>
Color.RED.name
# 'RED'
Color.RED.value
# (1, 0, 0)
Color.RED.hls
# (0.0, 0.5, 1.0)
type(Color.RED) is Color
# True
types.DynamicClassAttribute is a decorator that allows having a
Practically, it is used only in
@property
that behaves differently when it's called from the class and when from the instance.from types import DynamicClassAttribute
class Meta(type):
@property
def hello(cls):
return f'hello from Meta ({cls})'
class C(metaclass=Meta):
@DynamicClassAttribute
def hello(self):
return f'hello from C ({self})'
C.hello
# "hello from Meta (<class '__main__.C'>)"
C().hello
# 'hello from C (<__main__.C object ...)'
Practically, it is used only in
enum
to provide name
and value
properties for instances while still allowing to have name
and value
class members:import enum
class E(enum.Enum):
value = 1
E.value
# <E.value: 1>
E.value.value
# 1
The module zipapp can pack a python module into a zip archive that can be executed directly by a Python interpreter. It is a good way to ship CLI tools:
$ mkdir example
$ echo 'print("hello, @pythonetc!")' > example/__main__.py
$ python3 -m zipapp example
$ python3 example.pyz
hello, @pythonetc!