Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 以字符串形式获取变量的名称_Python_Variables - Fatal编程技术网

Python 以字符串形式获取变量的名称

Python 以字符串形式获取变量的名称,python,variables,Python,Variables,本线程讨论如何在Python中以字符串形式获取函数名: 如何对变量执行相同的操作?与函数相反,Python变量没有\uu name\uu属性 换句话说,如果我有一个变量,比如: foo = dict() foo['bar'] = 2 我正在寻找一个函数/属性,例如检索_name(),以便,其中列名由实际词典的名称给出: # List of dictionaries for my DataFrame list_of_dicts = [n_jobs, users, queues, priorit

本线程讨论如何在Python中以字符串形式获取函数名:

如何对变量执行相同的操作?与函数相反,Python变量没有
\uu name\uu
属性

换句话说,如果我有一个变量,比如:

foo = dict()
foo['bar'] = 2
我正在寻找一个函数/属性,例如
检索_name()
,以便,其中列名由实际词典的名称给出:

# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts] 

Python中唯一具有规范名称的对象是模块、函数和类,当然不能保证在定义函数或类或导入模块后,该规范名称在任何命名空间中都有任何意义。这些名称也可以在对象创建后进行修改,因此它们可能并不总是特别值得信任的


你想做的是不可能的;名称是对对象的单向引用。普通Python对象或花园式Python对象不包含对其名称的引用。想象一下,如果每个整数、每个dict、每个列表、每个布尔值都需要维护一个表示引用它的名称的字符串列表!这将是一场实现噩梦,对程序员几乎没有好处。

我认为这是不可能的。考虑下面的例子:

>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664
a
b
指向同一个对象,但对象不知道哪些变量指向它

>>> locals()['foo']
{}
>>> globals()['foo']
{}
如果您想编写自己的函数,可以这样做,您可以检查在局部变量中定义的变量,然后检查全局变量。如果找不到任何内容,可以在id()上进行比较,查看变量是否指向内存中的同一位置


如果变量在类中,可以使用className.dict.keys()或vars(self)查看变量是否已定义。

在Python中,
def
class
关键字将特定名称绑定到它们定义的对象(函数或类)。类似地,模块通过在文件系统中被称为特定的东西而被命名。在所有这三种情况下,都有一种明显的方法可以为所讨论的对象指定一个“规范”名称

但是,对于其他类型的对象,这样的规范名称可能根本不存在。例如,考虑列表的元素。列表中的元素没有单独命名,在程序中引用它们的唯一方法完全可能是使用包含列表的列表索引。如果将这样的对象列表传递到函数中,则不可能为值分配有意义的标识符

Python不会将赋值左侧的名称保存到赋值对象中,因为:

  • 这需要找出多个冲突对象中的“规范”名称
  • 对于从未分配给显式变量名的对象来说,这毫无意义
  • 效率极低,
  • 事实上,没有其他语言能做到这一点
  • 因此,例如,使用
    lambda
    定义的函数将始终具有“名称”
    ,而不是特定的函数名称


    最好的方法是让调用者输入一个(可选)姓名列表。如果键入
    “…”,“…”
    太麻烦,您可以接受一个包含逗号分隔的名称列表的字符串(如
    namedtuple

    即使变量值没有指向该名称,您也可以访问每个指定变量及其值的列表,所以我很惊讶,只有一个人建议在这里循环查找您的var名称

    有人在回答中提到,您可能需要遍历堆栈并检查每个人的本地和全局以查找
    foo
    ,但如果在调用此
    检索名称
    函数的范围内分配了
    foo
    ,您可以使用
    inspect
    current frame
    获取所有这些局部变量

    我的解释可能有点太罗嗦(也许我应该少用一个“foo”字),但下面是它在代码中的表现(注意,如果有多个变量分配给同一个值,您将得到这两个变量的名称):


    如果从另一个函数调用此函数,请执行以下操作:

    def foo(bar):
        return retrieve_name(bar)
    
    foo(baz)
    
    如果您想要的是
    baz
    而不是
    bar
    ,则只需进一步返回范围即可。这可以通过在
    调用者本地变量
    初始化中添加额外的
    .f\u back
    来完成

    请参见此处的示例:

    它是这样使用的:

    name(variable=variable)
    

    这里有一种方法。对于任何重要的事情我都不推荐这个,因为它会很脆。但这是可以做到的

    创建一个函数,该函数使用
    inspect
    模块查找调用它的源代码。然后,您可以解析源代码以识别要检索的变量名。例如,这里有一个名为
    autodict
    的函数,它获取变量列表并返回将变量名称映射到其值的字典。例如:

    x = 'foo'
    y = 'bar'
    d = autodict(x, y)
    print d
    
    将提供:

    {'x': 'foo', 'y': 'bar'}
    
    检查源代码本身比搜索
    locals()
    globals()
    要好,因为后者不会告诉您哪些变量是您想要的

    无论如何,代码如下:

    def autodict(*args):
        get_rid_of = ['autodict(', ',', ')', '\n']
        calling_code = inspect.getouterframes(inspect.currentframe())[1][4][0]
        calling_code = calling_code[calling_code.index('autodict'):]
        for garbage in get_rid_of:
            calling_code = calling_code.replace(garbage, '')
        var_names, var_values = calling_code.split(), args
        dyn_dict = {var_name: var_value for var_name, var_value in
                    zip(var_names, var_values)}
        return dyn_dict
    
    该操作发生在带有
    inspect.getouterframes
    的行中,该行返回调用
    autodict
    的代码中的字符串


    这种魔术的明显缺点是,它对源代码的结构进行了假设。当然,如果在解释器中运行,它将根本不起作用。

    在python3上,此函数将获得堆栈中最外层的名称:

    import inspect
    
    
    def retrieve_name(var):
            """
            Gets the name of var. Does it from the out most frame inner-wards.
            :param var: variable to get name from.
            :return: string
            """
            for fi in reversed(inspect.stack()):
                names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
                if len(names) > 0:
                    return names[0]
    
    它在代码的任何地方都很有用。遍历反向堆栈以查找第一个匹配项。

    def autodict(*args): get_rid_of = ['autodict(', ',', ')', '\n'] calling_code = inspect.getouterframes(inspect.currentframe())[1][4][0] calling_code = calling_code[calling_code.index('autodict'):] for garbage in get_rid_of: calling_code = calling_code.replace(garbage, '') var_names, var_values = calling_code.split(), args dyn_dict = {var_name: var_value for var_name, var_value in zip(var_names, var_values)} return dyn_dict

    import inspect
    
    
    def retrieve_name(var):
            """
            Gets the name of var. Does it from the out most frame inner-wards.
            :param var: variable to get name from.
            :return: string
            """
            for fi in reversed(inspect.stack()):
                names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
                if len(names) > 0:
                    return names[0]
    
    list_of_dicts = [n_jobs, users, queues, priorities]
    
    dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}
    
    from sorcery import dict_of
    
    columns = dict_of(n_jobs, users, queues, priorities)
    
    columns = dict(n_jobs=n_jobs, users=users, queues=queues, priorities=priorities)
    
    #direct get from called function code
    def retrieve_name_ex(var):
        stacks = inspect.stack()
        try:
            func = stacks[0].function
            code = stacks[1].code_context[0]
            s = code.index(func)
            s = code.index("(", s + len(func)) + 1
            e = code.index(")", s)
            return code[s:e].strip()
        except:
            return ""
    
    def whatis(string, x):
        print(string+' value=',repr(x),type(x))
        return string+' value='+repr(x)+repr(type(x))
    i_f=3.01
    i_n=int(i_f)
    i_s=str(i_n)
    i_l=[i_f, i_n, i_s]
    i_u=(i_f, i_n, i_s)
    
    ## make report that identifies all types
    report='\n'+20*'#'+'\nThis is the report:\n'
    report+= whatis('i_f ',i_f)+'\n'
    report+=whatis('i_n ',i_n)+'\n'
    report+=whatis('i_s ',i_s)+'\n'
    report+=whatis('i_l ',i_l)+'\n'
    report+=whatis('i_u ',i_u)+'\n'
    print(report)
    
    def retrieve_name(x, Vars=vars()):
        for k in Vars:
            if type(x) == type(Vars[k]):
                if x is Vars[k]:
                    return k
        return None
    
    import inspect
    
    def print_this(var):
        callers_local_vars = inspect.currentframe().f_back.f_locals.items()
        print(str([k for k, v in callers_local_vars if v is var][0])+': '+str(var))
    
    ***Input & Function call:***
    my_var = 10
    
    print_this(my_var)
    
    ***Output**:*
    my_var: 10
    
    import re
    def retrieve_name(func):
        return re.match("<function\s+(\w+)\s+at.*", str(func)).group(1)
    
    def foo(x):
        return x**2
    
    print(retrieve_name(foo))
    # foo
    
    >>> foo = dict()
    >>> f'{foo=}'.split('=')[0]
    'foo' 
    
    def Retriever(bar):
        return (list(globals().keys()))[list(map(lambda x: id(x), list(globals().values()))).index(id(bar))]
    
    class CustomDict(dict):
        def __add__(self, other):
            return CustomDict({**self, **other})
    
    class GlobalBase(type):
        def __getattr__(cls, key):
            return CustomDict({key: globals()[key]})
    
        def __getitem__(cls, keys):
            return CustomDict({key: globals()[key] for key in keys})
    
    class G(metaclass=GlobalBase):
        pass
    
    x, y, z = 0, 1, 2
    
    print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
    print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}
    
    A = [0, 1]
    B = [1, 2]
    pd.DataFrame(G.A + G.B) # It will return a data frame with A and B columns
    
    >> my_var = 5
    >> my_var_name = [ k for k,v in locals().items() if v == my_var][0]
    >> my_var_name 
    'my_var'
    
     >> my_var = 5
    >> my_var_name = [ k for k,v in locals().items() if v is my_var][0]
    >> my_var_name 
    'my_var'
    
    def getVariableName(variable, globalVariables=globals().copy()):
        """ Get Variable Name as String by comparing its ID to globals() Variables' IDs
    
            args:
                variable(var): Variable to find name for (Obviously this variable has to exist)
    
            kwargs:
                globalVariables(dict): Copy of the globals() dict (Adding to Kwargs allows this function to work properly when imported from another .py)
        """
        for globalVariable in globalVariables:
            if id(variable) == id(globalVariables[globalVariable]): # If our Variable's ID matches this Global Variable's ID...
                return globalVariable # Return its name from the Globals() dict
    
    def getVariableNames(variable):
        results = []
        globalVariables=globals().copy()
        for globalVariable in globalVariables:
            if id(variable) == id(globalVariables[globalVariable]):
                results.append(globalVariable)
        return results
    
    a = 1
    b = 1
    getVariableNames(a)
    # ['a', 'b']
    
    def find_var_name(val):
    
        dict_list = []
        global_dict = dict(globals())
    
        for k, v in global_dict.items():
            dict_list.append([k, v])
       
        return [item[0] for item in dict_list if item[1] == val]
    
    var1 = 'hello'
    var2 = 'hello'
    find_var_name('hello')
    
    ['var1', 'var2']