Python etc
Ir al canal en Telegram
Regular tips about Python and programming in general Owner — @pushtaev The current season is run by @orsinium Tips are appreciated: https://ko-fi.com/pythonetc / https://sobe.ru/na/pythonetc © CC BY-SA 4.0 — mention if repost
Mostrar másEl país no está especificadoTecnologías y Aplicaciones16 318
6 179
Suscriptores
Sin datos24 horas
Sin datos7 días
Sin datos30 días
Archivo de publicaciones
6 179
How many ways you know how to convert
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?6 179
types.SimpleNamespace is a way to make a
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 subscriptable6 179
Module numbers was introduced by PEP-3141 in Python 2.6. It implements the numbers hierarchy, inspired by Scheme:
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.6 179
Python caches every imported module is
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
# False6 179
Everything is an object, including functions, lambdas, and generators:
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
# 26 179
Every class is an instance of its metaclass. The default metaclass is
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,)6 179
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'6 179
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,
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.6 179
Python has NaN float value and it's a rule-breaking thing:
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.6 179
Meet the poll Friday! Every week there will be a poll about Python features and tools to see what is popular in the Python world. Share the polls in chats to get more results.
6 179
The famous "Zen of Python" was introduced in PEP-20. This is 19 aphorisms authored by Tim Peters. Do
import this in the Python interpreter to see them:
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
The fun thing is how this module looks like. The original text is encoded by ROT13 algorithm and is decoded on the fly:
s = """Gur Mra bs Clguba, ol Gvz Crgref
...
"""
d = {}
for c in (65, 97):
for i in range(26):
d[chr(i+c)] = chr((i+13) % 26 + c)
print("".join([d.get(c, c) for c in s]))
Some say it violates almost all the principles that it contains.6 179
ast.literal_eval is a restricted version of eval that evaluates only literals:
ast.literal_eval('[1, True, "three"]')
# [1, True, 'three']
ast.literal_eval('1+2')
# ValueError: malformed node or string: <_ast.BinOp object ...>
This can be used for safely evaluating strings containing Python values from untrusted sources. For example, to support types for environment variables. However, be aware that too large and complex string can crash the interpreter:
>>> import ast
>>> ast.literal_eval('1+1'*1000000)
[1] 32177 segmentation fault python36 179
Hamming distance is the number of positions at which the corresponding symbols are different. It's the simplest measure of difference between 2 strings and can be implemented in a few lines:
from itertools import zip_longest
def hamming(left, right):
return sum(sl != sr for sl, sr in zip_longest(left, right))
hamming('hello', 'hello')
# 0
hamming('hello', 'hallo')
# 1
hamming('hello', 'helol')
# 2