【问题标题】:return variable name from outside of function, as string inside python function从函数外部返回变量名,作为python函数内部的字符串
【发布时间】:2013-09-13 04:30:58
【问题描述】:

所以我创建了一个函数,该函数将一个动作(在这种情况下是数组与正弦曲线的逐点乘法,但这对我的问题无关紧要)应用于数组。

现在我创建了另一个函数,我想用它创建一个 string 的 python 代码,以便以后多次应用第一个函数。第二个函数的输入可以是stringarray,因此如果需要,我也可以在其自己的输出上使用第二个函数。我在字符串中获取变量名的方法在函数之外工作。

输入:

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 语句很好地返回了它的名字。

但是,当我在函数中使用它时,无论我给它什么输入,它实际上似乎都在 locals() 中寻找 var。不知何故,它不会从函数输入中获取 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不是?我在functionTWO 的定义中的列表理解中指定了var。通常,当我将列表推导与函数输入一起使用时,它可以正常工作。有谁知道为什么这里不是这种情况?提前谢谢!

编辑:所以我猜答案是不要。 Marcin 的类实现看起来更简洁,代码量也差不多。太糟糕了,我无法让它在函数中工作。对于其他关于使用变量名作为字符串的donts(实际上是其他想法)有this 问题,在那里我得到了上面对变量名的列表理解。

【问题讨论】:

  • 为什么不直接把变量名传给函数呢?这似乎比您现在尝试做的打字少得多。它也会更明确,更不容易出错。
  • @sybren 好吧,我希望能够在片场任意多次执行相同的功能。我可以很容易地在命令控制台中输入它感觉很愚蠢,但我不知道一个简单的方法来让一个函数做到这一点,所以我只是让函数输入它。猜猜有“更好”的方法。我会尝试学习它们:)

标签: python string function variables locals


【解决方案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)

虽然您可以通过一些技巧将对局部变量的引用传递到函数之外,但这并不是一个好主意,因为您最终会创建自己的半生不熟的对象系统,这更难理解。

* 这是因为一个变量有一个名字(它是一个字符串)和一个上下文,它把名字映射到字符串。所以,你至少需要传递一个元组才能真正传递一个变量。

【讨论】:

  • cannot 是一个比我使用的更强大的术语,但是是的 +1
  • @JoranBeasley 很公平,但正如 OP 的麻烦所证明的那样,它并不是真正传递变量,而是传递一个没有上下文的名称。
  • @Marcin 很好的解释,谢谢!仍然让我感到困扰的是,没有更快的方法可以让我自己在控制台中快速输入。你的解决方案比我的更优雅(最终我求助于为这个函数保留了一个全局 var )。为了能够使用您的解决方案,我将不得不研究什么是类以及它们是如何工作的。但我认为这不会是我最后一次需要它们。因此,感谢您的解决方案以及为什么不推荐我的方法的解释。
  • @Leo 不客气。如果您使用的是全局变量,那再次表明您应该使用一个类。简而言之,类就是您在上面看到的:声明 class <classname>(<baseclass>): 后跟一个函数(方法)列表,它们将类的实例作为它们的第一个参数 (self)。对象实例变量由self.<variable name> 访问。您可以通过调用类来创建实例(使用__init__ 的参数,self 除外)。实例具有与其他实例不同的变量(除非在类主体中定义)。
【解决方案2】:

将其全部包装到函数中时出现错误NameError: name 'var' is not defined 的原因如下:locals().items() 指的是本地定义的变量。事实上,函数中本地定义的变量只是函数内部定义的变量,以及作为参数传递给函数的变量。

顾名思义,locals().items() 是本地的,并且将由不同的变量组成,具体取决于它在脚本中的调用位置。

相反,globals().items() 包含所有全局变量,因此请尝试在您的函数中使用它,它应该可以解决问题。

有关更多信息,请查看 Python 中的全局变量和局部变量以及变量的范围。

【讨论】:

    【解决方案3】:

    presenter's answer适用于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'
    >>
    

    唯一的问题是它有点乱。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-23
      • 2013-08-16
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      相关资源
      最近更新 更多