【问题标题】:Python 2.7 using the input to a function as a string and variablePython 2.7 将函数的输入用作字符串和变量
【发布时间】:2012-07-02 10:28:55
【问题描述】:

我想做以下事情:

print "CC =",CC

但是作为一个函数,我只需要编写一次变量 CC。我无法弄清楚如何在函数中执行此操作,因为它总是将 CC 评估为浮点数(它是)......有没有办法接受函数的输入作为字符串和浮点号码?

我试过了:

def printme(a): 
    b='%s' % a
    print b
    return b

当然它只打印a 的值,而不是它的名字。

【问题讨论】:

  • Python 是动态类型的,所以简短的回答是“是的,当然!”。长答案取决于您尝试了什么,您能否分享一下您做了什么,出了什么问题以及您的预期?
  • 我已经尝试了多种方法,这是我尝试打印字符串和浮点数的一种方法,但它导致打印浮点并且没有字符串:
  • def printme(a): b='%s',a print b return b
  • 你为什么需要这个?用字典不是更有意义吗?
  • 继续阅读String formatting,看看你做错了什么;缺少% 运算符。

标签: python string floating-point


【解决方案1】:

您可以使用inspect 模块(另请参阅this SO question):

def printme(x):
    import inspect
    f = inspect.currentframe()
    val = f.f_back.f_locals[x]
    print x, '=', val


CC = 234.234    
printme('CC') # <- write variable name only once
# prints: CC = 234.234

【讨论】:

    【解决方案2】:

    也许字典是解决问题的更好方法。假设您有几个要使用的名称-值对,您可以将它们放在 dict 中:

    params = {"CC": 1.2345, "ID": "Yo!", "foo": "bar"}
    

    然后,例如,您可以打印所有格式正确的名称和值,如下所示:

    for key in params:
        print "{0} = {1}".format(key, params[key])
    

    但是由于目前还不清楚为什么你要这样做,所以很难判断这是否是正确的方法。

    【讨论】:

    • 原因是我只需要写一次CC而不是两次。我会经常这样做,所以速记很有用,我使用 python 的应用程序是科学计算,所以在编写数学算法时,你总是这样做来调试,例如在 matlab 中这非常简单,因为你只需输入变量名matlab 返回它的值。
    • +1 这不是 OP 想要的,但这是 OP 应该做的。我在 SO 上看到了很多与此类似的问题,每个问题最终都认为使用 dict 是解决问题的最方便和最 Pythonic 的方法。
    • @Vader,我看不出这个问题与字符串格式有关。 OP 的问题是如何在不显式提供 both 的情况下获取函数内部的变量名和值(“有没有办法将函数的输入作为既字符串和浮点数”和“……这样我只需要写一次变量 CC”)。
    • @catchmeifyoutry 当然这个问题不是关于格式化它是关于检索变量名。我想说的是,当您尝试在 Python 中获取变量名时,您可能做错了什么,解决问题的最佳方法是停止使用 hacks 并开始使用 dicts。
    • @Vader 啊,好吧,我们同意这个问题,只是不同意解决方案(对于这个特定的调试用例);)谢谢你澄清你的观点。
    【解决方案3】:

    我认为这是您需要的解决方案:

    def printme(x): 
        keys_list = [key for key, value in globals().iteritems() if value == x]
        print keys_list
        for key in keys_list:
            if id(globals()[key]) == id(x):
                result = "%s = %s" %(key, x)
                print result
                break
    
        return result
    

    例如,如果你声明一个变量:

    >>> c=55.6
    

    那么 printme(c) 的结果将是

    >>> 'c = 55.6'
    

    注意:此解决方案基于全局唯一 id 匹配。

    【讨论】:

    • 这仅在变量在globals 中时才有效,这意味着它对函数本地人无用...
    • @l4mpi 根据提出的问题,变量将被传递给函数。这意味着,该变量将不在该函数的 locals() 中,而是在 globals() 中。所以我首先检查了 globals() 。这可能不是确切的解决方案,但我认为它可以通过少量修改来提供所需的解决方案,即首先检查 locals()。
    • 这是错误的,表明您对变量范围的理解不足。如果变量在模块级别声明(或显式声明为全局),则该变量只会在globals 中。如果变量在另一个函数中声明,它既不会在globals 中,也不会在您的打印函数的locals 中——尝试def f(x): printme(x),然后调用f(1)。有关使用调用范围的本地变量的实际解决方案,请参阅 catchmeifyoutrys 答案。
    【解决方案4】:

    不完全是你想要的,但很容易做到:

    def printme(**kwargs):
        for key, value in kwargs.items():
            print '%s=%s' % (key, value)
        return value
    
    In [13]: printme(CC=1.23, DD=2.22)
    CC=1.23
    DD=2.22
    Out[13]: 1.23
    

    【讨论】:

      【解决方案5】:

      如果我理解正确的话,你想要这样的东西吗?

      def f(a):
          print('{0}: = {1}'.format(locals().keys()[0], a))
      

      更新:

      我知道这个例子没有多大意义,因为它基本上是一样的:

      def f(a):
          print('a: {0}'.format(a))
      

      我只是想将 OP 指向 locals(),因为我不太明白他想要完成什么。

      我想这就是他想要的更多:

      def f(**kwargs):
          for k in kwargs.keys():
              print('{0}: {1}'.format(k, kwargs[k]))
      
      
      f(a=1, b=2)
      

      【讨论】:

      • 这不起作用,因为变量不在函数的本地范围内
      • 这与写print 'a=%s' % a 完全相同,因为本地名称将始终为“a”。如果这确实是 OP 想要的,那么由于 Python 的工作方式,它无法完成。
      • 是的,几乎,这会导致打印以下内容:= 0.166666666667,我想要做的就是打印变量名,所以如果我要输入 f(x),我想得到 x = 0.166666666667 如果我要输入 f(b) 我想得到 b = 0.533 或任何 b
      • 第二个版本要求调用者使用关键字参数。它不适用于仅使用变量名。
      【解决方案6】:

      如果我理解正确,您想要在当前范围内打印变量名称及其值的简写吗? 如果不使用解释器跟踪函数或 sys._getframe,这通常是不可能的,通常只有在您知道自己在做什么的情况下才应该使用它。原因是 print 函数没有其他方法可以从调用范围内获取本地变量:

      def a():
          x = 1
          magic_print("x") #will not work without accessing the current frame
      

      没有这些你可以做的就是明确地将局部变量传递给这样的函数:

      def printNameAndValue(varname, values):
          print("%s=%s" % (varname, values[varname]))
      
      def a():
          x = 1
          printNameAndValue("x", locals())  #prints 'x=1'
      

      编辑:

      查看catchemifyoutry 的答案以获取使用inspect 模块(内部使用sys._getframe)的解决方案。为了完整起见,直接使用跟踪功能的解决方案 - 如果您使用 python 2.0 并且检查不可用,则很有用;)

      from sys import settrace
      
      __v = {} #global dictionary that holds the variables
      
      def __trace(frame, event, arg):
          """ a trace function saving the locals on every function call """
          global __v 
          if not event == "call":
              return __trace
          __v.update(frame.f_back.f_locals)
      
      def enableTrace(f):
          """ a wrapper decorator setting and removing the trace """
          def _f(*a, **kwa):
              settrace(__trace)
              try:
                  f(*a, **kwa)
              finally:
                  settrace(None)
          return _f
      
      def printv(vname):
          """ the function doing the printing """
          global __v 
          print "%s=%s" % (vname, __v[vname])
      

      将其保存在模块中并像这样使用:

      from modulenamehere import enableTrace, printv
      
      @enableTrace
      def somefunction():
          x = 1
          [...]
          printv("x")
      

      【讨论】:

      • 嗯,感谢您的努力,我认为您是正确的,因为没有解决方案,现在在我看来,我的原始解决方案是最好的解决方案,由于 python 抑制所有输入而出现困难默认情况下,实际上是一种禁用它的方法吗?
      • 不知道“抑制所有输入”是什么意思,但请参阅@catchmeifyoutry 的答案,了解使用检查(内部使用跟踪功能)的解决方案。
      【解决方案7】:

      使用了一个全局变量来实现这一点,func.__globals__.keys() 包含传递给func 的所有变量,所以我过滤掉了以__ 开头的名称并将它们存储在一个列表中。 每次调用 func() 时,func.__globals__.keys() 都会使用新的变量名称进行更新,因此将新的 varn 与旧的 glo 进行比较会得到刚刚添加的新变量。

      glo=[]
      def func(x):  
        global glo 
        varn=[x for x in func.__globals__.keys() if not x.startswith('__') and x!=func.__name__]
        new=list(set(varn)^set(glo))
        print("{0}={1}".format(new[0],x))
        glo=varn[:]
      

      输出:

      >>> a=10
      >>> func(a)
      a=10
      >>> b=20
      >>> func(20)
      b=20
      >>> foo='cat'
      >>> func(foo)
      foo=cat
      >>> bar=1000
      >>> func(bar)
      bar=1000
      

      【讨论】:

        猜你喜欢
        • 2018-01-10
        • 2017-02-27
        • 1970-01-01
        • 2011-03-30
        • 2021-06-27
        • 2022-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多