Як викликати setattr () на поточному модулі?


140

Що я передаю як перший параметр функції " object" setattr(object, name, value), щоб встановити змінні на поточному модулі?

Наприклад:

setattr(object, "SOME_CONSTANT", 42);

даючи такий же ефект, як:

SOME_CONSTANT = 42

всередині модуля, що містить ці рядки (з правильним object).

Я динамічно генерую декілька значень на рівні модуля, і оскільки я не можу визначитись __getattr__на рівні модуля, це мій запас.

Відповіді:


220
import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

або без використання setattr(що порушує букву питання, але задовольняє тим же практичним цілям ;-):

globals()[name] = value

Примітка : в області застосування модуля останній еквівалентний:

vars()[name] = value

який трохи більш стислий, але не працює в межах функції ( vars()дає змінні області, на яку він називається: змінні модуля, коли викликаються в глобальній області, і тоді добре використовувати R / W, але функція змінні, коли викликаються у функції, і тоді вона повинна трактуватися як R / O - онлайн-документи Python можуть бути дещо заплутаними щодо цього конкретного розрізнення).


9
Документи попереджають про зміну vars (). docs.python.org/library/functions.html#vars . Коли це добре робити?
unutbu

2
@ ~ unutbu, я б не сказав, що це цілком "нормально", але він буде працювати, коли ви зателефонуєте vars()на область модуля, а не всередині функції.
Майк Грехем

4
vars()еквівалентний globals()в області модуля (і так повертає істинний, модифікований дікт), але locals()в області функцій (і так повертає не змінюваний псевдодикт). Я використовую vars()в області модуля, оскільки він зберігає 3 символи, один склад, проти його синоніму в цій області globals();-)
Алекс Мартеллі,

14
Так, це знищило б найважливішу оптимізацію, яку робить компілятор Python: локальні змінні функції не зберігаються в диктаті, вони знаходяться у жорсткому векторі значень, і кожен локальний змінний доступ використовує індекс у цьому векторі, а не пошук імені. Щоб перемогти оптимізацію, змусивши дік, який ви хочете існувати, запустіть функцію з exec '': раз функціонуйте з декількома істотними петлями щоразу, і ви побачите важливість цієї оптимізації ядра для продуктивності Python.
Алекс Мартеллі

3
@msw, я думаю, ти забув "практичність б'є чистоту" ;-).
Алекс Мартеллі

6

Якщо вам потрібно встановити змінні області, що охоплюють модуль, всередині модуля, що з цим погано global?

# my_module.py

def define_module_scoped_variables():
    global a, b, c
    a, b, c = 'a', ['b'], 3

таким чином:

>>> import my_module
>>> my_module.define_module_scoped_variables()
>>> a
NameError: name 'a' is not defined
>>> my_module.a
'a'
>>> my_module.b
['b']

1
Так, я завжди (де "завжди" визначається як "останні кілька місяців, коли я навчався Python") вважав цю global but not reallyдекларацію дивним. Я припускаю, що це може бути історична реліквія, яка передує просторам імен модулів.
msw

1
Первісне запитання - це питання про те, як встановити атрибут, ім'я якого дається рядком (те саме, що я зараз шукав), тож це не допомогло б.
Керт


-1
  1. Ви б не зробили. Ви б зробилиglobals()["SOME_CONSTANT"] = 42
  2. Ви б не зробили. Ви зберігаєте динамічно генерований вміст де-небудь, крім модуля.

Так, SOME_CONSTANTобчислені під час виконання не зовсім постійні. А якщо вам globals()це недоступно, вам потрібно перейти до іншого модуля, щоб змінити його атрибути; це обов'язково змусить людей цікавитись.
msw

3
Постійне і змінне взаємно виключають. Постійні та динамічно генеровані не є. Значення, які я генерую, завжди однакові і визначаються на основі подальших "констант", щоб заощадити на арифметиці та введенні з мого боку.
Метт Столяр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.