Я впервые столкнулся с этим при попытке определить относительную производительность двух генераторов:
t = timeit.repeat('g.get()', setup='g = my_generator()')
Итак, я заглянул в модуль timeit и обнаружил, что setup и оператор оцениваются с их собственными, изначально пустыми пространствами имен, поэтому естественно, что привязка g никогда не станет доступной для оператора g.get (). Очевидное решение - заключить их в класс, добавив, таким образом, к глобальному пространству имен.
Я столкнулся с этим снова, пытаясь в другом проекте использовать многопроцессорный модуль для разделения задачи между работниками. Я даже все красиво упаковал в класс, но, к сожалению, звонок
pool.apply_async(runmc, arg)
завершается с ошибкой PicklingError, потому что похоронен внутри рабочего объекта, который запускает runmc, (фактически) назначение:
self.predicate = lambda x, y: x > y
так что весь объект нельзя (понятно) засолить, тогда как:
def foo(x, y):
return x > y
pickle.dumps(foo)
в порядке, последовательность
bar = lambda x, y: x > y
возвращает True из callable(bar)
и из type(bar)
, но это Can't pickle <function <lambda> at 0xb759b764>: it's not found as __main__.<lambda>
.
Я дал только фрагменты кода, потому что я могу легко исправить эти случаи, просто вытягивая их в определения уровня модуля или объекта. Ошибка здесь заключается в моем понимании семантики использования пространства имен в целом. Если природа языка требует, чтобы я создал больше def
утверждений, я с удовольствием это сделаю; Я боюсь, что мне не хватает важной концепции, хотя. Почему существует такая сильная зависимость от глобального пространства имен? Или что я не понимаю?
Пространства имен - одна из замечательных идей - давайте сделаем больше таких!