Вернуть имя переменной извне функции, как строку внутри функции python
Поэтому я создал функцию, которая применяет действие (в данном случае точечное умножение массива на синусоиду, но это не имеет значения для моего вопроса) к массиву.
Теперь я создал другую функцию, с помощью которой я хочу создать string
кода Python для применения первой функции несколько раз позже. Ввод второй функции может быть либо string
или array
, так что я могу использовать вторую функцию на своем собственном выходе, если это будет необходимо. Мой метод получения имени переменной в строке работает вне функции.
Вход:
var = np.array([[1,3],[2,4]]) # or sometimes var = 'a string'
if type(var)==str:
var_name = var
else:
var_name = [ k for k,v in locals().items() if v is var][0]
var_name
Выход:
'var'
Так вот var
переменная (массив или строка), предоставляемая функции, в данном случае массив. Оператор if возвращает мне свое имя.
Однако, когда я использую это внутри своей функции, независимо от того, какой ввод я даю, на самом деле кажется, что он ищет var в locals(). Каким-то образом это не берет var из функции ввода.
Определение:
def functionTWO(var, listoflistsofargs=None):
if type(var)==str:
var_name = var
else:
var_name = [ k for k,v in locals().items() if v is var][0]
if listoflistsofargs==None:
return var_name
command = []
for i in range(len(listoflistsofargs)):
if i==0:
command.append('functionONE(')
command.append(var_name)
command.append(',%.17f, %.17f)' % tuple(listoflistsofargs[i]))
else:
command.insert(0,'functionONE(')
command.append(',%.17f, %.17f)' % tuple(listoflistsofargs[i]))
''.join(command)
command[0] = var_name + ' + ' + command[0]
return ''.join(command)
Вход:
somearray = np.array([[1,2,3],[1,2,3],[1,2,3]])
args = [[1,3],[6,5]]
command = functionTWO(somearray, args)
command
Выход:
NameError: name 'var' is not defined
Требуемый выход:
'functionONE(functionONE(somearray, 1, 3), 6, 5)'
Почему listoflistsofargs
взяты из функции ввода и var
не? Я уточняю var
в списке осмысления в определении functionTWO
, Обычно, когда я использую списки со входами функций, это работает нормально. Кто-нибудь знает, почему это не так? Заранее спасибо!
РЕДАКТИРОВАТЬ: Так что я думаю, что ответ не так. Реализация классов Марсином выглядит намного чище и примерно в том же порядке, что и объем кода. Жаль, что я не мог заставить это работать внутри функции. Для других донатов (фактически других идей) об использовании имен переменных в качестве строк возникает вопрос, где я получил приведенный выше список для имен переменных.
3 ответа
Вы не можете передать переменную в виде строки *, и вы не должны этого делать.
Если вы хотите передать значение между функциями, обычным способом является его передача в качестве параметра, а в качестве возвращаемого значения.
Если это неудобно, обычным решением является объект: определите класс, который содержит как разделяемую переменную, так и методы, которые воздействуют на переменную.
Если вам нужно создать командные объекты, гораздо лучше сделать это структурированным способом. Например, если вы хотите передать функцию и параметры, вы можете буквально передать объект функции и параметры в кортеже:
def foo():
return (functionONE,somearray,1,3)
command = foo()
command[0](*command[1:])
Если вы хотите встроить такие команды в команды, вы, вероятно, захотите заключить это в класс, чтобы вы могли рекурсивно оценить параметры. На самом деле, вот маленький оценщик:
def evaluator(object):
def __init__(self,func=None,params=None):
self.func = func
self.params = params
def eval(self,alternativeparams=None):
if alternativeparams is not None:
params = alternativeparams
else:
params = self.params
if params is not None:
evaluatedparams = (item() if callable(item) else item for item in params)
else: evaluatedparams = None
if func is not None:
return self.func(*(evaluatedparams or ()))
else: return evaluatedparams
def __call__(self, *params):
return self.eval(params if params else None)
Хотя есть хаки, с помощью которых вы можете передавать ссылки на локальные переменные из функции, это не очень хорошая идея, потому что вы в конечном итоге создаете свою собственную полуобработанную объектную систему, которую труднее понять.
*
Это потому, что переменная имеет имя (которое является строкой) и контекст, который отображает имена в строки. Итак, вам нужно, по крайней мере, передать кортеж, чтобы действительно передать переменную.
Ответ ведущего работает в Python 3
def get_variable_name(*variable):
return [ k for k,v in globals().items() if v is variable[0]][0]
пример:
>> test = 'sample string'
>> get_variable_name(test)
'test'
>>
Единственная проблема - это немного грязно.
Причина, по которой вы получаете ошибку NameError: name 'var' is not defined
когда вы заключаете все это в функцию, происходит следующее: locals().items()
относится к локально определенным переменным. на самом деле локально определенные переменные в ваших функциях - это только переменные, определенные внутри функции, и переменные, переданные в качестве аргументов функции.
Как следует из названия, locals().items()
является локальным и будет состоять из разных переменных в зависимости от того, где он вызывается в вашем скрипте.
Напротив globals().items()
состоит из всех глобальных переменных, поэтому попробуйте использовать его вместо этого в своих функциях, это должно сработать.
Для получения дополнительной информации посмотрите глобальные и локальные переменные, а также область видимости переменных в Python.