将变量名作为字符串获取

问题:将变量名作为字符串获取

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

如何对变量执行相同操作?与函数相反,Python变量没有__name__属性。

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

foo = dict()
foo['bar'] = 2

我正在寻找一个功能/属性,例如retrieve_name(),以便从此列表在Pandas中创建一个DataFrame,其中列名由实际字典的名称给出:

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

This thread discusses how to get the name of a function as a string in Python: How to get a function name as a string?

How can I do the same for a variable? As opposed to functions, Python variables do not have the __name__ attribute.

In other words, if I have a variable such as:

foo = dict()
foo['bar'] = 2

I am looking for a function/attribute, e.g. retrieve_name() in order to create a DataFrame in Pandas from this list, where the column names are given by the names of the actual dictionaries:

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

回答 0

使用该python-varname包,您可以轻松检索变量的名称

https://github.com/pwwang/python-varname

就您而言,您可以执行以下操作:

from varname import Wrapper

foo = Wrapper(dict())

# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2

或者,您也可以尝试直接检索变量名称:

from varname import nameof

foo = dict()

fooname = nameof(foo)
# fooname == 'foo'

我是这个软件包的作者。如果您有任何疑问,请告诉我,或者可以在github上提交问题。

Using the python-varname package, you can easily retrieve the name of the variables

https://github.com/pwwang/python-varname

In your case, you can do:

from varname import Wrapper

foo = Wrapper(dict())

# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2

For list comprehension part, you can do:

n_jobs = Wrapper(<original_value>) 
users = Wrapper(<original_value>) 
queues = Wrapper(<original_value>) 
priorities = Wrapper(<original_value>) 

list_of_dicts = [n_jobs, users, queues, priorities]
columns = [d.name for d in list_of_dicts]
# ['n_jobs', 'users', 'queues', 'priorities']
# REMEMBER that you have to access the <original_value> by d.value

You can also try to retrieve the variable name DIRECTLY:

from varname import nameof

foo = dict()

fooname = nameof(foo)
# fooname == 'foo'

Note that this is working in this case as you expected:

n_jobs = <original_value>
d = n_jobs

nameof(d) # will return d, instead of n_jobs
# nameof only works directly with the variable

I am the author of this package. Please let me know if you have any questions or you can submit issues on Github.


回答 1

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

如果不递归地遍历命名对象的树,你要做的就是不可能; 名称是对对象的单向引用。常见的或具有花园多样性的Python对象不包含对其名称的引用。想象一下,如果要维护代表表示引用它的名称的字符串列表,是否需要每个整数,每个字典,每个列表,每个布尔值!这将是实施的噩梦,对程序员几乎没有好处。

The only objects in Python that have canonical names are modules, functions, and classes, and of course there is no guarantee that this canonical name has any meaning in any namespace after the function or class has been defined or the module imported. These names can also be modified after the objects are created so they may not always be particularly trustworthy.

What you want to do is not possible without recursively walking the tree of named objects; a name is a one-way reference to an object. A common or garden-variety Python object contains no references to its names. Imagine if every integer, every dict, every list, every Boolean needed to maintain a list of strings that represented names that referred to it! It would be an implementation nightmare, with little benefit to the programmer.


回答 2

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

在该答复中提到有人说,你可能必须走栈和检查每个人的当地人和全局找到foo,但如果foo在你调用这个范围被分配retrieve_name的功能,你可以用inspectcurrent frame,让你所有的局部变量。

我的解释可能有点罗word(也许我应该少用“ foo”一词),但这是它在代码中的样子(请注意,如果有多个变量分配给相同的值,您将获得这两个变量名):

import inspect

x,y,z = 1,2,3

def retrieve_name(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    return [var_name for var_name, var_val in callers_local_vars if var_val is var]

print retrieve_name(y)

如果要从另一个函数调用此函数,则类似:

def foo(bar):
    return retrieve_name(bar)

foo(baz)

而您想要baz代替bar,则只需进一步返回范围。这可以通过.f_backcaller_local_vars初始化中添加额外的内容来完成。

在这里查看示例:ideone

Even if variable values don’t point back to the name, you have access to the list of every assigned variable and its value, so I’m astounded that only one person suggested looping through there to look for your var name.

Someone mentioned on that answer that you might have to walk the stack and check everyone’s locals and globals to find foo, but if foo is assigned in the scope where you’re calling this retrieve_name function, you can use inspect‘s current frame to get you all of those local variables.

My explanation might be a little bit too wordy (maybe I should’ve used a “foo” less words), but here’s how it would look in code (Note that if there is more than one variable assigned to the same value, you will get both of those variable names):

import inspect

x,y,z = 1,2,3

def retrieve_name(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    return [var_name for var_name, var_val in callers_local_vars if var_val is var]

print retrieve_name(y)

If you’re calling this function from another function, something like:

def foo(bar):
    return retrieve_name(bar)

foo(baz)

And you want the baz instead of bar, you’ll just need to go back a scope further. This can be done by adding an extra .f_back in the caller_local_vars initialization.

See an example here: ideone


回答 3

使用Python 3.8可以简单地使用f字符串调试功能:

>>> foo = dict()
>>> f'{foo=}'.split('=')[0]
'foo' 

With Python 3.8 one can simply use f-string debugging feature:

>>> foo = dict()
>>> f'{foo=}'.split('=')[0]
'foo' 

回答 4

在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]

它在代码中的任何地方都很有用。遍历反向堆栈以查找第一个匹配项。

On python3, this function will get the outer most name in the stack:

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]

It is useful anywhere on the code. Traverses the reversed stack looking for the first match.


回答 5

我不认为这是可能的。考虑以下示例:

>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664

ab指向同一个对象,但对象无法知道指向它哪些变量。

I don’t believe this is possible. Consider the following example:

>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664

The a and b point to the same object, but the object can’t know what variables point to it.


回答 6

def name(**variables):
    return [x for x in variables]

它的用法如下:

name(variable=variable)
def name(**variables):
    return [x for x in variables]

It’s used like this:

name(variable=variable)

回答 7

这是一种方法。我不会推荐任何重要的东西,因为它会很脆。但这是可以完成的。

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

x = 'foo'
y = 'bar'
d = autodict(x, y)
print d

将给出:

{'x': 'foo', 'y': 'bar'}

检查源代码本身比搜索locals()or 更好,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

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

Here’s one approach. I wouldn’t recommend this for anything important, because it’ll be quite brittle. But it can be done.

Create a function that uses the inspect module to find the source code that called it. Then you can parse the source code to identify the variable names that you want to retrieve. For example, here’s a function called autodict that takes a list of variables and returns a dictionary mapping variable names to their values. E.g.:

x = 'foo'
y = 'bar'
d = autodict(x, y)
print d

Would give:

{'x': 'foo', 'y': 'bar'}

Inspecting the source code itself is better than searching through the locals() or globals() because the latter approach doesn’t tell you which of the variables are the ones you want.

At any rate, here’s the code:

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

The action happens in the line with inspect.getouterframes, which returns the string within the code that called autodict.

The obvious downside to this sort of magic is that it makes assumptions about how the source code is structured. And of course, it won’t work at all if it’s run inside the interpreter.


回答 8

我编写了包裹法术来稳健地执行这种魔术。你可以写:

from sorcery import dict_of

columns = dict_of(n_jobs, users, queues, priorities)

并将其传递给dataframe构造函数。等效于:

columns = dict(n_jobs=n_jobs, users=users, queues=queues, priorities=priorities)

I wrote the package sorcery to do this kind of magic robustly. You can write:

from sorcery import dict_of

columns = dict_of(n_jobs, users, queues, priorities)

and pass that to the dataframe constructor. It’s equivalent to:

columns = dict(n_jobs=n_jobs, users=users, queues=queues, priorities=priorities)

回答 9

>>> locals()['foo']
{}
>>> globals()['foo']
{}

如果要编写自己的函数,可以这样做,以便可以检查在本地变量中定义的变量,然后检查全局变量。如果未找到任何内容,则可以在id()上进行比较,以查看变量是否指向内存中的相同位置。

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

>>> locals()['foo']
{}
>>> globals()['foo']
{}

If you wanted to write your own function, it could be done such that you could check for a variable defined in locals then check globals. If nothing is found you could compare on id() to see if the variable points to the same location in memory.

If your variable is in a class, you could use className.dict.keys() or vars(self) to see if your variable has been defined.


回答 10

在Python中,defandclass关键字会将特定名称绑定到它们定义的对象(函数或类)。同样,模块被称为文件系统中的特定名称。在这三种情况下,都有一种明显的方法可以为所讨论的对象分配“规范”名称。

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

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

  1. 这就需要弄清楚在多个冲突对象中哪个名称是“规范的”,
  2. 对于从未分配给显式变量名称的对象没有任何意义,
  3. 效率极低,
  4. 从字面上看,没有其他语言可以做到这一点。

因此,例如,使用定义的函数lambda将始终具有“ name” <lambda>,而不是特定的函数名。

最好的方法是简单地要求调用方法传递一个(可选)名称列表。如果键入'...','...'太麻烦,则可以接受例如包含逗号分隔的名称列表的单个字符串(就像namedtuple这样)。

In Python, the def and class keywords will bind a specific name to the object they define (function or class). Similarly, modules are given a name by virtue of being called something specific in the filesystem. In all three cases, there’s an obvious way to assign a “canonical” name to the object in question.

However, for other kinds of objects, such a canonical name may simply not exist. For example, consider the elements of a list. The elements in the list are not individually named, and it is entirely possible that the only way to refer to them in a program is by using list indices on the containing list. If such a list of objects was passed into your function, you could not possibly assign meaningful identifiers to the values.

Python doesn’t save the name on the left hand side of an assignment into the assigned object because:

  1. It would require figuring out which name was “canonical” among multiple conflicting objects,
  2. It would make no sense for objects which are never assigned to an explicit variable name,
  3. It would be extremely inefficient,
  4. Literally no other language in existence does that.

So, for example, functions defined using lambda will always have the “name” <lambda>, rather than a specific function name.

The best approach would be simply to ask the caller to pass in an (optional) list of names. If typing the '...','...' is too cumbersome, you could accept e.g. a single string containing a comma-separated list of names (like namedtuple does).


回答 11

>> my_var = 5
>> my_var_name = [ k for k,v in locals().items() if v == my_var][0]
>> my_var_name 
'my_var'

locals()-返回包含当前范围的局部变量的字典。通过遍历该字典,我们可以检查具有等于定义的变量的值的键,仅提取键将为我们提供字符串格式的变量文本。

来自(经过一些更改) https://www.tutorialspoint.com/How-to-get-a-variable-name-as-a-string-in-Python

>> my_var = 5
>> my_var_name = [ k for k,v in locals().items() if v == my_var][0]
>> my_var_name 
'my_var'

locals() – Return a dictionary containing the current scope’s local variables. by iterating through this dictionary we can check the key which has a value equal to the defined variable, just extracting the key will give us the text of variable in string format.

from (after a bit changes) https://www.tutorialspoint.com/How-to-get-a-variable-name-as-a-string-in-Python


回答 12

我认为用Python做到这一点是如此困难,因为一个简单的事实,就是您永远不会知道所使用的变量的名称。因此,在他的示例中,您可以执行以下操作:

代替:

list_of_dicts = [n_jobs, users, queues, priorities]

dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}

I think it’s so difficult to do this in Python because of the simple fact that you never will not know the name of the variable you’re using. So, in his example, you could do:

Instead of:

list_of_dicts = [n_jobs, users, queues, priorities]

dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}

回答 13

这是基于输入变量的内容执行此操作的另一种方法:

(它返回与输入变量匹配的第一个变量的名称,否则返回None。可以对其进行修改以获取与输入变量具有相同内容的所有变量名称)

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

just another way to do this based on the content of input variable:

(it returns the name of the first variable that matches to the input variable, otherwise None. One can modify it to get all variable names which are having the same content as input variable)

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

回答 14

此函数将打印变量名称及其值:

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

This function will print variable name with its value:

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

回答 15

我有一种方法,虽然不是最有效的 …但是有效!(并且它不涉及任何高级模块)。

基本上,它将变量的IDglobals()变量的ID进行比较,然后返回匹配项的名称。

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

I have a method, and while not the most efficient…it works! (and it doesn’t involve any fancy modules).

Basically it compares your Variable’s ID to globals() Variables’ IDs, then returns the match’s name.

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

回答 16

如果目标是帮助您跟踪变量,则可以编写一个简单的函数来标记变量并返回其值和类型。例如,假设i_f = 3.01并将其四舍五入为一个称为i_n的整数以在代码中使用,然后需要一个字符串i_s并将其输入报告中。

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)

在每次调用时,此命令都会打印到窗口中以进行调试,并为书面报告生成一个字符串。唯一的缺点是,每次调用该函数时,必须两次键入该变量。

我是Python的新手,发现这种非常有用的方式可以记录我在编程时的工作并尝试处理Python中的所有对象。一个缺点是,如果whatis()调用在使用它的过程之外描述的函数,则它将失败。例如,int(i_f)是有效的函数调用,仅是因为Python知道了int函数。您可以使用int(i_f ** 2)调用whatis(),但是如果出于某些奇怪的原因而选择定义一个名为int_squared的函数,则必须在使用whatis()的过程中声明它。

If the goal is to help you keep track of your variables, you can write a simple function that labels the variable and returns its value and type. For example, suppose i_f=3.01 and you round it to an integer called i_n to use in a code, and then need a string i_s that will go into a report.

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)

This prints to the window at each call for debugging purposes and also yields a string for the written report. The only downside is that you have to type the variable twice each time you call the function.

I am a Python newbie and found this very useful way to log my efforts as I program and try to cope with all the objects in Python. One flaw is that whatis() fails if it calls a function described outside the procedure where it is used. For example, int(i_f) was a valid function call only because the int function is known to Python. You could call whatis() using int(i_f**2), but if for some strange reason you choose to define a function called int_squared it must be declared inside the procedure where whatis() is used.


回答 17

也许这可能是有用的:

def Retriever(bar):
    return (list(globals().keys()))[list(map(lambda x: id(x), list(globals().values()))).index(id(bar))]

该函数遍历全局作用域中值的ID列表(可以编辑命名空间),根据其ID查找所需/所需的var或函数的索引,然后从基于以下名称的全局名称列表中返回名称在获取的索引上。

Maybe this could be useful:

def Retriever(bar):
    return (list(globals().keys()))[list(map(lambda x: id(x), list(globals().values()))).index(id(bar))]

The function goes through the list of IDs of values from the global scope (the namespace could be edited), finds the index of the wanted/required var or function based on its ID, and then returns the name from the list of global names based on the acquired index.


回答 18

以下方法不会返回变量的名称,但是如果变量在全局范围内可用,则使用此方法可以轻松创建数据框。

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

Following method will not return the name of variable but using this method you can create data frame easily if variable is available in global scope.

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

回答 19

对于常量,可以使用枚举,该枚举支持检索其名称。

For constants, you can use an enum, which supports retrieving its name.


回答 20

我尝试从本地检查人员那里获取名称,但是它无法处理像a [1],b.val这样的var。之后,我有了一个新主意—从代码中获取var名称,然后尝试使用succ!如下代码:

#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 ""

I try to get name from inspect locals, but it cann’t process var likes a[1], b.val. After it, I got a new idea — get var name from the code, and I try it succ! code like below:

#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 ""

回答 21

您可以尝试以下操作来检索定义的函数的名称(尽管不适用于内置函数):

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

You can try the following to retrieve the name of a function you defined (does not work for built-in functions though):

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