
Esta é a sétima seleção de dicas e programação em Python do meu feed @pythonetc.
Seleções anteriores:
Vários contextos
Às vezes, pode ser necessário executar um bloco de código em vários gerenciadores de contexto:
with open('f') as f: with open('g') as g: with open('h') as h: pass
Desde o Python 2.7 e 3.1, isso pode ser feito com uma única expressão:
o = open with o('f') as f, o('g') as g, o('h') as h: pass
Antes, você poderia usar a função
contextlib.nested
:
with nested(o('f'), o('g'), o('h')) as (f, g, h): pass
Se você trabalha com um número indefinido de gerenciadores de contexto, é melhor escolher ferramentas mais avançadas.
contextlib.ExitStack
permite inserir qualquer número de contextos a qualquer momento e garante a saída deles no final da execução:
with ExitStack() as stack: f = stack.enter_context(o('f')) g = stack.enter_context(o('g')) other = [ stack.enter_context(o(filename)) for filename in filenames ]
Objetos na memória do intérprete
Todos os objetos que estão atualmente na memória do intérprete podem ser acessados usando
gc.get_objects()
:
In : class A: ...: def __init__(self, x): ...: self._x = x ...: ...: def __repr__(self): ...: class_name = type(self).__name__ ...: x = self._x ...: return f'{class_name}({x!r})' ...: In : A(1) Out: A(1) In : A(2) Out: A(2) In : A(3) Out: A(3) In : [x for x in gc.get_objects() if isinstance(x, A)] Out: [A(1), A(2), A(3)]
Dígitos
In : int('୧৬༣') Out: 163
0 1 2 3 4 5 6 7 8 9
não são os únicos caracteres considerados dígitos. O Python segue as regras Unicode e conta várias centenas de caracteres como números. Lista completa
aqui .
Isso é importante para funções como
int
,
unicode.isdecimal
e até
re.match
:
In : int('௯') Out: 9 In : '٢'.isdecimal() Out: True In : bool(re.match('\d', '౫')) Out: True
Meia-noite UTC
>>> bool(datetime(2018, 1, 1).time()) False >>> bool(datetime(2018, 1, 1, 13, 12, 11).time()) True
Antes do Pyhon 3.5, os objetos
datetime.time()
eram considerados falsos se representassem a meia-noite UTC. Isso pode levar a erros não óbvios. No exemplo a seguir,
if not
poderá falhar porque não
create_time
é
None
, mas porque é meia-noite.
def create(created_time=None) -> None: if not created_time: created_time = datetime.now().time()
Você pode contornar esse bug verificando explicitamente a opção
None
:
if created_time is None
.
Trabalho assíncrono no FS
O Python não suporta operações de arquivos assíncronas. Para torná-los sem bloqueio, você precisa usar threads.
Para execução assíncrona de código em um fluxo, você precisa usar o método
loop.run_in_executor
.
Um módulo
aiofiles
terceiros pode fazer isso por você, fornecendo uma interface simples e conveniente:
async with aiofiles.open('filename', mode='r') as f: contents = await f.read()