Return имя переменной извне функции, как строка внутри функции 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. Обычно, когда я пользуюсь списками с функциями ввода, он работает нормально. Кто-нибудь знает, почему это не так? Заранее благодарю вас!

EDIT: Итак, я думаю, что ответ не. Реализация классов Marcin выглядит намного чище и примерно того же порядка количества кода. Жаль, что я не мог заставить это работать внутри функции. Для других donts (фактически других идей) об использовании имен переменных в качестве строк существует этот вопрос, где я получил приведенное выше понимание списка для имен переменных.

Ответ 1

Вы не можете передать переменную как строку *, и вы не должны этого делать.

Если вы хотите передать значение между функциями, обычный способ - передать его в качестве параметра и вывести его как возвращаемое значение.

Если это неудобно, обычным решением является объект: определите класс, который несет как общую переменную, так и методы, которые действуют на переменную.

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

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)

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

* Это связано с тем, что переменная имеет имя (это строка) и контекст, который отображает имена в строки. Итак, вам нужно, по крайней мере, передать кортеж, чтобы действительно передать переменную.

Ответ 2

Причина, по которой вы получаете сообщение об ошибке NameError: name 'var' is not defined при переносе всего ее в функцию, следующая: locals().items() относится к локально определенным переменным. на самом деле локально определенные переменные в ваших функциях - это только переменные, определенные внутри функции, и те, которые переданы в качестве аргументов функции.

Как сказано в названии, locals().items() является локальным и будет состоять из разных переменных в зависимости от того, где он вызывается в вашем script.

Наоборот, globals().items() состоит из всех глобальных переменных, поэтому попробуйте использовать его вместо этого в своих функциях, он должен сделать трюк.

Для получения дополнительной информации просмотрите глобальные и локальные переменные, а также область переменных в Python.

Ответ 3

Ответ на презентацию в 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'
>>

Единственная проблема - это немного грязно.