Как получить / установить локальные переменные функции (извне) в Python? - PullRequest
9 голосов
/ 01 сентября 2009

Если у меня есть функция (в Python 2.5.2), например:

def sample_func():
    a = 78
    b = range(5)
    #c = a + b[2] - x

Мои вопросы:

  1. Как получить локальные переменные (a, b) функции извне без , используя locals () внутри функции? (вид отражения)
  2. Можно ли установить локальную переменную (скажем, x ) извне, чтобы закомментированная строка работала? (Я знаю, это звучит странно).

Заранее спасибо.

EDIT

Все просят вариант использования. Но это странная ситуация. (Не вините меня, я не создал это). Вот сценарий:

  1. У меня есть зашифрованный исходный файл python, содержащий функцию python.
  2. Модуль расширения C расшифровывает его и создает эту функцию в памяти.
  3. Основная программа на Python сначала вызывает расширение C с этим местоположением зашифрованного файла.
  4. Затем основная программа вызывает встроенную в память функцию (с расширением C)
  5. Но основной программе нужно знать локальные переменные этой функции (не спрашивайте меня, почему, это был не я)
  6. По какой-то (чертовски) причине основной программе тоже нужно установить переменную (самая странная из всех)

Ответы [ 5 ]

16 голосов
/ 01 сентября 2009

Нет. Функция, которая не запускается, не имеет локальных объектов; это просто функция. Спрашивать, как изменить локальные функции, когда они не запущены, все равно что спрашивать, как изменить кучу программы, когда она не запущена.

Вы можете изменить константы, если действительно хотите.

def func():
    a = 10
    print a

co = func.func_code
modified_consts = list(co.co_consts)
for idx, val in enumerate(modified_consts):
    if modified_consts[idx] == 10: modified_consts[idx] = 15

modified_consts = tuple(modified_consts)

import types
modified_code = types.CodeType(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, modified_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab)
modified_func = types.FunctionType(modified_code, func.func_globals)
# 15:
modified_func()

Это хак, потому что нет способа узнать, какая константа в co.co_consts есть какая; это использует значение часового, чтобы выяснить это. В зависимости от того, можете ли вы ограничить свои варианты использования, этого может быть достаточно.

8 голосов
/ 01 сентября 2009

Я не уверен, каков ваш вариант использования, но это может работать лучше в классе. Вы можете определить метод __call__, чтобы класс вел себя как функция.

например:.

>>> class sample_func(object):
...     def __init__(self):
...         self.a = 78
...         self.b = range(5)
...     def __call__(self):
...         print self.a, self.b, self.x
... 
>>> f = sample_func()
>>> print f.a
78
>>> f.x = 3
>>> f()
78 [0, 1, 2, 3, 4] 3

(это основано на вашем игрушечном примере, поэтому код не имеет особого смысла. Если вы дадите больше деталей, мы сможем предоставить более качественный совет)

1 голос
/ 03 сентября 2009

Ожидается, что переменная в функции будет установлена ​​внешней функцией ДО того, как эта функция будет вызвана, настолько плохой дизайн, что единственный реальный ответ, который я могу порекомендовать, - это изменение дизайна. Функция, которая ожидает, что ее внутренние переменные будут установлены до ее запуска, бесполезна.

Итак, реальный вопрос, который вы должны задать, - почему эта функция ожидает, что x будет определен вне функции? Использует ли исходная программа, в которой эта функция принадлежит, установить глобальную переменную, к которой у этой функции был бы доступ? Если это так, то это может быть так же просто, как предложить первоначальным авторам этой функции, чтобы они вместо этого позволили передавать x в качестве аргумента. Простое изменение в вашей функции-примере заставит код работать в обеих ситуациях:

def sample_func(x_local=None):
  if not x_local:
    x_local = x
  a = 78
  b = range(5)
  c = a + b[2] - x_local

Это позволит функции принимать параметр из вашей основной функции так, как вы хотите его использовать, но не сломает другую программу, поскольку все равно будет использовать глобально определенный x, если функции не даны какие-либо аргументы.

1 голос
/ 02 сентября 2009

Не уверен, что это именно то, что вы имеете в виду, но так как функции являются объектами в Python, вы можете привязать переменные к объекту функции и получить к ним доступ извне:

def fa():
    print 'x value of fa() when entering fa(): %s' % fa.x
    print 'y value of fb() when entering fa(): %s' % fb.y
    fa.x += fb.y
    print 'x value of fa() after calculation in fa(): %s' % fa.x
    print 'y value of fb() after calculation in fa(): %s' % fb.y
    fa.count +=1


def fb():
    print 'y value of fb() when entering fb(): %s' % fb.y
    print 'x value of fa() when entering fa(): %s' % fa.x
    fb.y += fa.x
    print 'y value of fb() after calculation in fb(): %s' % fb.y
    print 'x value of fa() after calculation in fb(): %s' % fa.x
    print 'From fb() is see fa() has been called %s times' % fa.count


fa.x,fb.y,fa.count = 1,1,1

for i in range(10):
    fa()
    fb()

Пожалуйста, извините, если я ужасно неправ ... Я сам начинающий на Python и программировании ...

1 голос
/ 01 сентября 2009

Локальные значения функции меняются при каждом запуске функции, поэтому нет смысла обращаться к ним, пока функция не запущена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...