从函数返回后,如何在 Python 中打印原始变量的名称?
- 2025-01-17 09:23:00
- admin 原创
- 45
问题描述:
我有枚举并使用诸如、等变量myEnum.SomeNameA
。myEnum.SomeNameB
当我从函数返回其中一个变量时,我可以打印它们的名称(例如myEnum.SomeNameA
)而不是它们返回的值吗?
解决方案 1:
简短的回答:不。
长答案:使用回溯、检查等一些丑陋的黑客手段可以实现这一点,但通常不建议将其用于生产代码。例如,请参阅:
http://groups.google.com/group/comp.lang.python/msg/237dc92f3629dd9a?pli=1
http://aspn.activestate.com/ASPN/Mail/Message/python-Tutor/330294
也许您可以使用一种解决方法将值转换回名称/表示字符串。如果您发布更多示例代码和有关您想要此内容的详细信息,也许我们可以提供更深入的帮助。
解决方案 2:
不存在唯一或原始的变量名
http://www.amk.ca/quotations/python-quotes/page-8
这与你获取在门廊上发现的那只猫的名字的方式相同:猫(对象)本身无法告诉你它的名字,而且它并不真正关心 - 所以找出它叫什么的唯一方法就是询问你所有的邻居(命名空间)这是否是他们的猫(对象)......
....如果您发现它有很多名字,或者根本没有名字,请不要感到惊讶!
Fredrik Lundh,2000 年 11 月 3 日,回答问题“当我有 PyObject* 时,如何从 C++ 中获取变量的名称?”
解决方案 3:
补充@Jay 的回答,一些概念......
Python 的“变量”只是对值的引用。每个值都占据一个给定的内存位置(参见id()
):
>>> id(1)
10052552
>>> sys.getrefcount(1)
569
从上面,您可能会注意到该值1
存在于内存位置 10052552。在解释器的这个实例中,它被引用了 569 次。
>>> MYVAR = 1
>>> sys.getrefcount(1)
570
现在,可以看到,由于另一个名称与该值绑定,引用计数增加了一。
基于这些事实,判断哪个单个变量名指向某个值是不现实/不可能的。
我认为解决问题的最佳方法是将映射和函数添加到枚举引用中并返回到字符串名称:
myEnum.get_name(myEnum.SomeNameA)
解决方案 4:
Python 3.8 增加了一个新的、可能更好的解决方案:
my_nice_variable_name = 'test'
print(f'{my_nice_variable_name=}')
# Output:
# my_nice_variable_name='test'
这里你可以使用字符串输出。仍然不建议这样做,但可能比其他方法好一点。
解决方案 5:
是的
import inspect
def printVariableName(abc):
newvar=inspect.stack()[1][4][0]
print(newvar.split("(")[1].split(")")[0])
noob=10
printVariableName(noob)
输出:
noob
解决方案 6:
是的。
对于枚举的情况,这很容易:
>>> 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>
一般来说,它可能会模棱两可:
>>> 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']
甚至具有误导性:
>>> 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)]'
要在任何范围内搜索,请使用以下命令:
>>> 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']
为了避免歧义,请将您的姓名用数据包裹起来。
解决方案 7:
只需使用要打印的文本作为枚举的值,如下所示
class MyEnum (object):
valueA = "valueA"
valueB = "valueB"
在 Python 中,比较字符串的一致性几乎与比较整数值一样高效(这是因为字符串是不可变的,并且具有哈希值)
当然,首先有更简单的方法来创建枚举:
class Enum (object):
def __init__(self, *values):
for v in values:
self.__dict__[v] = v
然后,像这样创建枚举:
MyEnum = Enum("valueA", "valueB")
按照和上面相同的方式访问:
MyEnum.valueA
解决方案 8:
这个问题有两个答案:是和否。
你能做到吗?——能(大多数情况下)
值得吗?——不值得(大多数情况下)
如何操作:
这取决于枚举的实现。例如:
class Enum:
A = 1
B = 2
如果您知道枚举类对象以及该类中的所有名称(或至少是唯一的前缀),那么是否有 100 个名称指的是您想要查找其名称的整数并不重要。
对于上面的例子,正如@batbrat建议的,你可以Enum.__dict__
使用以下方法检查' ' namestr()
:
>>> getEnum = lambda: Enum.A
>>> namestr(getEnum(), Enum.__dict__)
>>> ['A']
在这种情况下,您甚至不必知道所有枚举名称。如果枚举的实现方式不同,那么您可能需要使用不同的 hack。在大多数情况下都会有一些解决方案,例如,参见@Jay 的答案。但这并不重要,因为……
这值得吗?
一些枚举实现可能需要丑陋、复杂并且最终不可靠的黑客来实现
namestr()
。枚举类可以自行返回答案(参见@David、@Ber、@gahooa 的答案)。
正如@Ber 指出的那样, Python 中没有内置的 Enum 和 switch 语句(请参阅PEP-0275、PEP-3103)。值得研究没有枚举的解决方案。
解决方案 9:
您可以将规范名称存储为实例的属性,然后将其分配给具有相同名称的变量。这可能会奏效:
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
无论如何,这并不是一件特别“Pythonic”的事情。
解决方案 10:
再想想:
由于 Python 不提供原生的枚举类型,因此您不应该要求提供这种类型,而应该使用其他更强大的构造来构建程序。否则,下一步必然会是“为什么 Python 没有语句switch ...:
,我该如何最好地模拟它?”
由于枚举通常用于定义某种状态,因此更好的方法是:创建一个基类,定义属于某个状态的所有抽象属性、特性和方法。然后,为每个状态派生一个子类,实现该状态的特定行为。然后,您可以传递这些类(或可能是其实例)来处理状态及其行为。
如果您使用类而不是实例(Python 的“单例”方式),您可以简单地通过if current_state is StateA:
(注意是is
用 而不是==
)检查任何给定的状态(这不是必要的),并且与比较整数值相比不会造成性能损失。
当然,您可以定义一个name
属性和__str__()
方法来访问和打印州的名称。
解决方案 11:
Erlang 有一个概念叫“原子”——它们类似于字符串常量或枚举。考虑使用字符串常量作为枚举的值——与枚举的名称相同。
解决方案 12:
据我所知,这需要一些自省。您可以尝试使用检查模块。
在此之前,您可能需要尝试一些简单的事情:
这不是应该使用的确切代码。您必须在打印之前从 dict 中检索变量名称。
打印 myEnum.__dict__
如果您想从函数内部打印变量名称,可以尝试以下函数 - vars()、locals() 和 globals()。
编辑:
我刚刚注意到这不是您想要的。在这种情况下,添加一个字典和一个函数可能会有效
您可能想要打印枚举类的__dict__。
尽管如此,Python 中没有标准枚举。了解如何创建它们会有所帮助。
再想想,你可以将变量作为枚举中的字典来维护,以变量名称为键,并提供枚举方法来查找正确的变量并打印其名称。这种解决方案(保留字典)很糟糕,因为变量值不一定是唯一的。
编辑:
这个问题并不简单,所以你可能需要使用一个经过尝试和测试的解决方案。恕我直言,如果可以的话,你最好避免这种情况。
解决方案 13:
我知道这是一个老问题但使用是可能的f strings
。
my_variable = some_object
f'{my_variable=}'.split('=', 1)[0]
这将打印'my_variable'
解决方案 14:
f 字符串可以做到这一点:
def log(obj):
print(f"{obj=})
x = 5
log(x)
>>> x=5
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)