Comments 9
так же я придерживаюсь практики говорящих названий функций и классов. это позволяет избежать колизий да и вообще улучшает читаемость. «get_habr_like_count()» — мало шансов что перечётся с иными функциями из других библиотек
from dis import dis
def foo():
import math
return math.pi
def bar():
from math import pi
return pi
dis(foo)
dis(bar)
Выхлоп будет примерно таким: foo() | bar()
|
# import math | # from math import pi
0 LOAD_CONST 1 (0) | 0 LOAD_CONST 1 (0)
2 LOAD_CONST 0 (None) | 2 LOAD_CONST 2 (('pi',))
4 IMPORT_NAME 0 (math) | 4 IMPORT_NAME 0 (math)
6 STORE_FAST 0 (math) | 6 IMPORT_FROM 1 (pi)
| 8 STORE_FAST 0 (pi)
| 10 POP_TOP
# return math.pi |
8 LOAD_FAST 0 (math) |
10 LOAD_ATTR 1 (pi) | # return pi
12 RETURN_VALUE | 12 LOAD_FAST 0 (pi)
| 14 RETURN_VALUE
Действительно, в обоих вариантах модуль импортируется целиком, что неудивительно — в модуле может быть код инициализации (а может и не быть).Видна также выгода от импорта аттрибута модуля — при обращении к нему экономится аж целый
LOAD_ATTR
. Это очень быстрый опкод, но иногда хочется еще быстрее.from timeit import timeit
setup = """
import math
from math import pi
def foo(): return math.pi
def bar(): return pi
def baz(): return __import__('math').pi"""
print(timeit('foo()', setup=setup))
print(timeit('bar()', setup=setup))
print(timeit('baz()', setup=setup))
Выхлоп:0.09096475400019699
0.06547341800069262
0.221324110999376
Отличная статья, а как влияет на импортирование модуля и классов из него условие if name == “main”?
Если модуль импортируется любым способом, то его __name__
!= "__main__"
, всё что внутри if
не выполняется.
А еще можно в этот процесс добавить немного магии и импортировать динамически созданные сущности: https://plumbum.readthedocs.io/en/latest/local_commands.html#import-hack
from module import *
нервно курит в сторонке
Импорт со звёздочкой идёт в лес.
В PEP8 даны достаточно однозначные рекомендации, которые не сложно соблюдать.
А еще flake8 умеет ругаться на использование F403 ‘from module import *’ used; unable to detect undefined names.
# __init__.py
from .module_1 import *
from .module_2 import *
...
Это помогает создать удобную используемость, не нужно знать точное местоположение функций в иерархии пакетов (естественно при условии что имена будут уникальными).
Я предпочитаю явно задавать публичное API модуля.
При звёздочках надо заполнять __all__
или получишь всё что есть внутри. Если свои аттрибуты можно спрятать через правильное именование (начать с нижнего подчёрквания) то что делать с теми которые импортируешь?
from my_module import pprint
Если выбирать между импортировать руками или написать в __all__
все аттрибуты руками в виде строк, то мне проще сделать явные импорты. А еще это уменьшает когнитивную нагрузку у читающих, им не надо знать про __all__
.
Import or from import, that is the question