Я читал что-то около дня назад, не мог вспомнить, где, и автор сообщения отметил, что лучше связывать вызовы функций с именем в локальном пространстве, а не создавать .
вызов доступа.
Например:
def foo():
a = math.cos
b = math.sin
x = a(1) * b(0)
против
def foo():
x = math.cos(1) * math.sin(0)
Теперь это было в контексте производительности, и если эти звонки были сделаны не один раз, но мне стало интересно, почему он вообще работает лучше и когда его следует использовать так? Разве это не просто затмевает пространство имен?
Я сделал некоторое профилирование, чтобы понять, какова фактическая разница между ними. Вы можете найти REPL здесь из timeit import timeit
import math
from math import sin
x = 10_000_000
def from_import():
for _ in range(x):
sin(100)
def import_module():
for _ in range(x):
math.sin(100)
def local_var():
s = math.sin
for _ in range(x):
s(100)
def local_import():
from math import sin
for _ in range(x):
sin(100)
funcs = (from_import, import_module, local_var, local_import)
for func in funcs:
print("{:<15} {}".format(
func.__name__, timeit(
func.__name__ + '()', number=1, globals=globals())))
Результаты, достижения:
from_import 4.354339323996101
import_module 5.608195230990532
local_var 3.982630196987884
local_import 3.9956486110022524
Я был удивлен, что локальные имена были намного более эффективными по глобальным именам. Оба значительно превосходят дополнительные атрибуты.