简体   繁体   English

从函数返回后,如何在 Python 中打印原始变量的名称?

[英]How to print original variable's name in Python after it was returned from a function?

我有枚举并使用myEnum.SomeNameAmyEnum.SomeNameB等变量。当我从函数返回这些变量之一时,我可以打印它们的名称(例如myEnum.SomeNameA )而不是它们返回的值吗?

Short answer: no.简短的回答:没有。

Long answer: this is possible with some ugly hacks using traceback, inspect and the like, but it's generally probably not recommended for production code.长答案:使用回溯、检查等进行一些丑陋的黑客攻击是可能的,但通常可能不建议将其用于生产代码。 For example see:例如见:

Perhaps you can use a workaround to translate the value back to a name/representational string.也许您可以使用一种解决方法将值转换回名称/表示字符串。 If you post some more sample code and details about what you're wanting this for maybe we can provide more in-depth assistance.如果您发布更多示例代码和有关您想要此内容的详细信息,也许我们可以提供更深入的帮助。

There is no such thing as a unique or original variable name http://www.amk.ca/quotations/python-quotes/page-8没有唯一或原始变量名称这样的东西http://www.amk.ca/quotations/python-quotes/page-8

The same way as you get the name of that cat you found on your porch: the cat (object) itself cannot tell you its name, and it doesn't really care -- so the only way to find out what it's called is to ask all your neighbours (namespaces) if it's their cat (object)...就像你得到你在门廊上找到的那只猫的名字一样:猫(物体)本身不能告诉你它的名字,它并不真正关心——所以找出它叫什么的唯一方法是询问所有邻居(命名空间)是否是他们的猫(对象)...

....and don't be surprised if you'll find that it's known by many names, or no name at all! ....如果您发现它有很多名字,或者根本没有名字,请不要感到惊讶!

Fredrik Lundh, 3 Nov 2000, in answer to the question "How can I get the name of a variable from C++ when I have the PyObject*?" Fredrik Lundh,2000 年 11 月 3 日,回答了“当我拥有 PyObject* 时如何从 C++ 获取变量的名称?”的问题。

To add to @Jay's answer , some concepts...要添加到@Jay 的回答中,一些概念...

Python "variables" are simply references to values. Python“变量”只是对值的引用。 Each value occupies a given memory location (see id() )每个值占据一个给定的内存位置(见id()

>>> id(1)
10052552

>>> sys.getrefcount(1)
569

From the above, you may notice that the value "1" is present at the memory location 10052552. It is referred to 569 times in this instance of the interpreter.从上面,您可能会注意到值“1”出现在内存位置 10052552 处。在这个解释器实例中,它被引用了 569 次。

>>> MYVAR = 1
>>> sys.getrefcount(1)
570

Now, see that because yet another name is bound to this value, the reference count went up by one.现在,看到因为另一个名称绑定到这个值,引用计数增加了一个。

Based on these facts, it is not realistic/possible to tell what single variable name is pointing to a value.基于这些事实,判断哪个单个变量名称指向一个值是不现实的/不可能的。

I think the best way to address your issue is to add a mapping and function to your enum reference back to a string name.我认为解决您的问题的最佳方法是将映射和函数添加到您的枚举引用回字符串名称。

myEnum.get_name(myEnum.SomeNameA) 

Please comment if you would like sample code.如果您需要示例代码,请发表评论。

Yes.是的。

In your case with enums, it's easy:在您使用枚举的情况下,这很容易:

>>> from enum import Enum
>>> class Type(Enum):
...   AB, SBS, INTERLACED, SPLIT = range(4)
...
>>> Type.AB
<Type.AB: 0>
>>> print(Type.AB)
Type.AB
>>> Type.AB.name
'AB'
>>> Type.AB.value
0
>>> Type(0)
<Type.AB: 0>

In general, it could be ambiguous:一般来说,它可能是模棱两可的:

>>> def varname(v): d = globals(); return [k for k in d if d[k] == v]
...
>>> def varnameis(v): d = globals(); return [k for k in d if d[k] is v]
...
>>> foo = {'a':'aap'}
>>> bar = {'a':'aap'}
>>> varname(foo)
['foo', 'bar']
>>> varnameis(foo)
['foo']

Or even misleading:甚至误导:

>>> foo = "A"; bar = "A"
>>> varnameis("A")
['foo', 'bar']
>>> foo = "An immutable value."; bar = "An immutable value."
>>> varnameis("An immutable value.")
[]
>>> foo = "An immutable value."; bar = "An immutable value."; varnameis("An immutable value.")
['foo', 'bar']
>>> import sys; sys.version
'3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 02:47:15) [MSC v.1900 32 bit (Intel)]'

To search in any scope, use this:要在任何范围内搜索,请使用以下命令:

>>> def varname(v, scope=None): d = globals() if not scope else vars(scope); return [k for k in d if d[k] == v]
...
>>> import time
>>> time.timezone
-3600
>>> varname(-3600)
[]
>>> varname(-3600, time)
['timezone']

To avoid ambiguity, wrap your name with the data .为避免歧义,请将您的姓名用 data 包裹起来

Python 3.8 added a new and probably a LITTLE better solution to this: Python的3.8增添了新的可能有点较好地解决了这一点:

my_nice_variable_name = 'test'
print(f'{my_nice_variable_name=}')

# Output:
# my_nice_variable_name='test'

Here you could work with the string output.在这里,您可以使用字符串输出。 Still not advisable but maybe a little better than other ways of doing it.仍然不可取,但可能比其他方法好一点。

Just use the text you want to print as the value of the enum, as in只需使用要打印的文本作为枚举的值,如

class MyEnum (object):
    valueA = "valueA"
    valueB = "valueB"

comparing strings for identity is almost as efficient in Python as is comparing integer values (this is due to the fact the strings are immutable as have a hash value)在 Python 中比较字符串的身份几乎和比较整数值一样有效(这是因为字符串是不可变的,因为具有哈希值)

Of course there are easier ways to create the enum in the first place:当然,首先有更简单的方法来创建枚举:

class Enum (object):
    def __init__(self, *values):
        for v in values:
            self.__dict__[v] = v

Then, create you enumeration like this:然后,像这样创建枚举:

MyEnum = Enum("valueA", "valueB")

ans access the same way as above: ans 访问方式与上述相同:

MyEnum.valueA

There are two answers to this question: Yes and No .这个问题有两个答案: YesNo

Can you do it?  -- Yes (in most cases)
Is it worth it? -- No  (in most cases)

How to do it:怎么做:

It depends on an implementation of enums.这取决于枚举的实现。 For example:例如:

class Enum:
    A = 1
    B = 2

It doesn't matter whether there are 100 names refers to an integer whose name you'd like to find if you know enums class object and all they're names (or at least a unique prefix) in that class .如果您知道 enums 类对象以及它们在该类中的所有名称(或至少是唯一的前缀),那么是否有 100 个名称指的是一个整数并不重要。

For the example above as @batbrat suggested you can inspect ' Enum.__dict__ ' using namestr() :对于上面@batbrat 建议的示例,您可以使用namestr()检查“ Enum.__dict__ ”:

 >>> getEnum = lambda: Enum.A
 >>> namestr(getEnum(), Enum.__dict__)
 >>> ['A']

In this case you even don't have to know all enum names.在这种情况下,您甚至不必知道所有枚举名称。 If enums implemented differently then you might need to use a different hack.如果枚举的实现方式不同,那么您可能需要使用不同的 hack。 There will be some solution in most cases eg, see @Jay's answer .在大多数情况下会有一些解决方案,例如,请参阅@Jay 的回答 But it doesn't matter because..不过没关系,因为..

Is it worth it?这值得么?

  • Some enum implementations may require ugly, complex and in the end unreliable hacks to implement namestr() .一些枚举实现可能需要丑陋、复杂且最终不可靠的技巧来实现namestr()

  • Enum class can return answer by itself (see @David's , @Ber's , @gahooa's answers). Enum 类可以自行返回答案(请参阅@David's@Ber's@gahooa 的答案)。

  • As @Ber pointed out there is no builtin Enum and switch statement in Python (see PEP-0275 , PEP-3103 ).正如@Ber 指出的那样,Python 中没有内置的 Enum 和 switch 语句(参见PEP-0275PEP-3103 )。 It is worth investigating solutions without enums.值得研究没有枚举的解决方案。

You could store the canonical name as an attribute of the instance, and then assign it to a variable with the same name.您可以将规范名称存储为实例的属性,然后将其分配给具有相同名称的变量。 This might work:这可能有效:

class MyEnum(object):
    def __new__(cls, name):
        try:
            return getattr(MyEnum, name)
        except AttributeError:
            e = super(MyEnum, cls).__new__(cls)
            e.name = name
            setattr(MyEnum, name, e)
            return e

Regardless, it's not a particularly "Pythonic" thing to do.无论如何,这不是一件特别“Pythonic”的事情。

YES是的

import inspect
        
def printVariableName(abc):
    newvar=inspect.stack()[1][4][0]
    print(newvar.split("(")[1].split(")")[0])

noob=10
printVariableName(noob)

Output:输出:

noob

On second thought:第二个想法:

Since Python does not provide native Enum types, you should not ask for one, but instead use other, more powerful construct to build your program.由于 Python 不提供本机 Enum 类型,您不应该要求一种,而是使用其他更强大的构造来构建您的程序。 Otherwise, the next step will invariably be "Why does Python not have a switch ...: statement, and how do I best emulate it?"否则,下一步将始终是“为什么 Python 没有switch ...:语句,我该如何最好地模拟它?”

Since Enums are often used to define some kind of state, a much better approach is this: Create a base class that define all the abstract properties, attributes and methods belonging to a state.由于枚举通常用于定义某种状态,因此更好的方法是:创建一个基类来定义属于某个状态的所有抽象属性、属性和方法。 Then, for each state, derive a sub class that implements the specific behavior of this state.然后,对于每个状态,派生一个实现该状态特定行为的子类。 You can then pass around these classes (or maybe instances thereof) to handle the state and its behaviour.然后,您可以传递这些类(或者可能是它们的实例)来处理状态及其行为。

If you use classes instead of instances (the Python way of a "singleton"), you can simply check for any given state (not that it should be necessary) by if current_state is StateA: (note the is instead of == ) with no performance penalty over comparing integer values.如果您使用类而不是实例(“单例”的 Python 方式),您可以简单地通过if current_state is StateA:来检查任何给定的状态(不是它应该是必需的) if current_state is StateA:注意is而不是== )比较整数值没有性能损失。

And of course, you can define a name attribute and a __str__() method to access and print the state's name.当然,您可以定义name属性和__str__()方法来访问和打印状态的名称。

As far as I know, that will require some introspection.据我所知,这需要一些内省。 You can try using the inspect module.您可以尝试使用检查模块。

There are a few simple things you may want to try before that:在此之前,您可能想尝试一些简单的事情:

  1. This is not the exact code that should be used.这不是应该使用的确切代码。 You will have to retrieve the variable name from __dict__ before printing.您必须在打印之前从 __dict__ 检索变量名称。
    \nprint myEnum.__dict__打印 myEnum.__dict__\n        
  2. If you want to print the variable name from inside the function, you can try the functions - vars(), locals() and globals().如果你想从函数内部打印变量名,你可以尝试函数 - vars()、locals() 和 globals()。
    Edit :编辑
    I just noticed that this is not what you want.我只是注意到这不是你想要的。 In that case adding a dict and a function may work在这种情况下,添加一个 dict 和一个函数可能会起作用
  3. You may want to print the __dict__ of the class of your enums.您可能想要打印枚举类的 __dict__。

All that said, there aren't standard enumerations in Python.尽管如此,Python 中没有标准的枚举。 It would help to know how you are creating them.了解您如何创建它们会有所帮助。

On second thoughts, you can maintain your variables as a dictionary in the enum, keyed by variable name and provide a method of the enumeration to find the right variable and print its name.再想一想,您可以将变量作为枚举中的字典维护,以变量名称为键,并提供一种枚举方法来查找正确的变量并打印其名称。 This solution (keeping a dict) is bad because variable values aren't necessarily unique.这个解决方案(保留字典)很糟糕,因为变量值不一定是唯一的。

Edit :编辑
The problem is not trivial, so you may want to use a tried and tested solution.这个问题并非微不足道,因此您可能需要使用久经考验的解决方案。 IMHO, you would be better off avoiding the situation if you can.恕我直言,如果可以的话,你最好避免这种情况。

Erlang has a concept called "atoms" -- they are similar to string constants or enumerations. Erlang 有一个叫做“原子”的概念——它们类似于字符串常量或枚举。 Consider using a string constant as the value of your enum -- the same as the name of the enum.考虑使用字符串常量作为枚举的值——与枚举的名称相同。

I know it's a an old question but it's possible using f strings .我知道这是一个老问题,但可以使用f strings

my_variable = some_object
f'{my_variable=}'.split('=', 1)[0]

this would print 'my_variable'这将打印'my_variable'

lol simply use f'strings大声笑只是使用 f'strings

text = 'no sir' print(f'{text=}') text = 'no Sir' 打印(f'{text=')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM