имеют ли библиотеки Python естественную зависимость от глобального пространства имен? - PullRequest
1 голос
/ 29 марта 2010

Я впервые столкнулся с этим при попытке определить относительную производительность двух генераторов:

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 утверждений, я с удовольствием это сделаю; Я боюсь, что мне не хватает важной концепции, хотя. Почему существует такая сильная зависимость от глобального пространства имен? Или что я не понимаю?

Пространства имен - одна из замечательных идей - давайте сделаем больше таких!

1 Ответ

3 голосов
/ 29 марта 2010

Протокол (ы) pickle будет иметь серьезные проблемы при выборе классов и функций в наиболее общем случае; вместо этого, выбирая их «по имени», это устраняет сложность, но в конечном итоге требует, чтобы они были связаны (и могут быть восстановлены) с именами верхнего уровня в модуле (который, поскольку модуль является его собственным пространством имен, в конце концов, не конфликтует с «пространствами имен - это одна гудящая отличная идея»;

Что касается вашей timeit проблемы, я не понимаю, что вы имеете в виду под "глобальным пространством имен" - например:

>>> timeit.repeat('g.get(23)', 'g = {}')
[0.29134988784790039, 0.27160286903381348, 0.27237796783447266]

пространство имен, к которому привязан g, оставляет привязку полностью доступной повторяющимся оператором Если то, что вы связываете с g, является генератором, возможно, ваша проблема в том, что у генераторов нет .get() методов, и, возможно, вы имели в виду .next()?

...