Resumo : neste tutorial, você examinará as variantes da instrução de importação do Python e como elas funcionam nos bastidores.
módulo de importação
Quando você importa um módulo, o Python faz duas coisas:
- Primeiro, verifique se o módulo foi carregado e armazenado em cache em sys.modules. Caso contrário, ele executará o módulo e criará uma referência ao objeto do módulo.
- Segundo, adicione o nome do módulo ao namespace global que faz referência ao mesmo objeto de módulo.
O programa a seguir importa o módulo matemático e imprime o math
objeto no sys.modules
namespace global:
import sys
import math
print('sys.modules:', hex(id(sys.modules['math'])))
if 'math' in globals():
print('globals: ', hex(id(globals()['math'])))
Linguagem de código: JavaScript ( javascript )
Saída:
sys.modules: 0x20456766590
globals: 0x20456766590
Linguagem de código: HTTP ( http )
Como você pode ver, a math
variável faz referência ao mesmo objeto de módulo.
Se você importar um módulo pela segunda vez, o Python não executará o math
módulo novamente, mas o obterá do sys.modules
cache.
do objeto de importação do módulo
Quando você importa um objeto (uma função , uma classe , etc.,) de um módulo, o Python faz o seguinte:
- Primeiro, verifique se o módulo foi carregado e armazenado em cache no arquivo
sys.modules
. Caso contrário, ele executará o módulo e criará uma referência ao objeto do módulo. - Segundo, adicione o objeto de importação ao namespace global.
Nesse caso, Python não adiciona uma variável que faz referência ao módulo ao namespace global, mas uma variável que faz referência ao objeto importado.
O exemplo a seguir importa a ceil
função do math
objeto:
import sys
from pprint import pprint
from math import ceil
print('sys.modules:', hex(id(sys.modules['math'])))
pprint(globals())
Linguagem de código: JavaScript ( javascript )
Saída:
sys.modules: 0x11d659c2130
{'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__cached__': None,
'__doc__': None,
'__file__': 'C:/oop/app.py',
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000011D65A008E0>,
'__name__': '__main__',
'__package__': None,
'__spec__': None,
'ceil': <built-in function ceil>,
'pprint': <function pprint at 0x0000011D661C4040>,
'sys': <module 'sys' (built-in)>}
Linguagem de código: PHP ( php )
Neste exemplo, Python carrega o math
módulo no arquivo sys.modules
. No entanto, ele cria apenas uma referência à ceil
função, não ao math
objeto do módulo no namespace global.
do objeto de importação do módulo como object_alias
Quando você carrega um objeto de um módulo e usa um alias, o Python fará o seguinte:
- Primeiro, verifique se o módulo foi carregado e armazenado em cache no arquivo
sys.modules
. Caso contrário, ele executará o módulo e criará uma referência ao objeto do módulo. - Segundo, crie um alias que faça referência ao objeto importado e adicione-o ao namespace global.
Por exemplo, o seguinte importa a ceil
função do módulo matemático e usa o alias de teto:
import sys
from math import ceil as ceiling
print('sys.modules:', hex(id(sys.modules['math'])))
print('globals:', hex(id(globals()['ceiling'])))
Linguagem de código: JavaScript ( javascript )
Saída:
sys.modules: 0x1cc4f244ae0
{'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__cached__': None,
'__doc__': None,
'__file__': 'C:/oop/app.py',
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001CC4EA708E0>,
'__name__': '__main__',
'__package__': None,
'__spec__': None,
'ceiling': <built-in function ceil>,
'pprint': <function pprint at 0x000001CC4F234040>,
'sys': <module 'sys' (built-in)>}
Linguagem de código: PHP ( php )
da importação do módulo *
Ao importar tudo de um módulo, o Python fará o seguinte:
- Primeiro, verifique se o módulo foi carregado e armazenado em cache em sys.modules. Caso contrário, ele executará o módulo e criará uma referência ao objeto do módulo.
- Segundo, adicione todos os símbolos do módulo ao namespace global .
Por exemplo, o seguinte importa todos os objetos do módulo matemático:
import sys
from pprint import pprint
from math import *
print('sys.modules:', hex(id(sys.modules['math'])))
pprint(globals())
Linguagem de código: JavaScript ( javascript )
Saída:
sys.modules: 0x1e1ebf24b30
{'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__cached__': None,
'__doc__': None,
'__file__': 'C:/oop/app.py',
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E1EB7408E0>,
'__name__': '__main__',
'__package__': None,
'__spec__': None,
'acos': <built-in function acos>,
'acosh': <built-in function acosh>,
'asin': <built-in function asin>,
....
'tau': 6.283185307179586,
'trunc': <built-in function trunc>}
Linguagem de código: PHP ( php )
Como você pode ver claramente na saída, Python adiciona todas as funções do módulo matemático aos namespaces globais. Nesse caso, se existir algum símbolo no namespace global, o Python substituirá suas referências.
Isso geralmente leva a bugs que são difíceis de rastrear. Portanto, você deve evitar usar o módulo from import *
Equívoco de importação de Python
Um dos equívocos mais comuns da declaração de importação é que muitos consideram a seguinte declaração:
from math import ceil
Linguagem de código: JavaScript ( javascript )
é mais eficiente do que:
import math
Linguagem de código: JavaScript ( javascript )
Porque a primeira instrução importa apenas a ceil
função, enquanto a segunda instrução importa o math
módulo inteiro.
No entanto, o Python carrega o math
módulo inteiro em ambos os casos.
A primeira instrução cria um símbolo que faz referência à ceil
função do math
módulo, enquanto a segunda instrução cria o math
símbolo que faz referência ao math
objeto do módulo.
Resumo
- A instrução Python
import
carrega um módulo apenas uma vez e o armazena em cache no arquivosys.modules
. - Evite usar o
from module import *
porque pode causar um bug. - Não use
from module import object
para otimizar a velocidade do programa porque isso não acontecerá.