我在python中有一个变量x。如何从变量中找到字符串'x'。这是我的尝试:
def var(v,c):
for key in c.keys():
if c[key] == v:
return key
def f():
x = '321'
print 'Local var %s = %s'%(var(x,locals()),x)
x = '123'
print 'Global var %s = %s'%(var(x,locals()),x)
f()
结果是:
Global var x = 123
Local var x = 321
上面的食谱似乎有些不同寻常。是否有更好/更短的方法来实现相同的结果?
答案 0 :(得分:13)
答:如果我正确理解你的问题,你想要从变量的值到它的名字。这在Python中确实不可能。
在Python中,确实没有任何“变量”这样的东西。 Python真正拥有的是“名称”,它们可以绑定对象。它对象可能会绑定哪些名称(如果有的话)没有区别。它可能会绑定几十个不同的名称,或者没有名称。
考虑这个例子:
foo = 1
bar = foo
baz = foo
现在,假设你有一个值为1的整数对象,并且你想要向后工作并找到它的名字。你会打印什么?三个不同的名称将该对象绑定到它们,并且所有这些都同样有效。
print(bar is foo) # prints True
print(baz is foo) # prints True
在Python中,名称是访问对象的一种方式,因此无法直接使用名称。您可以搜索locals()
以查找值并恢复名称,但这最多只是一个客厅技巧。在上面的示例中,foo
,bar
和baz
中的哪一个是“正确”答案?它们都指的是完全相同的对象。
P.S。上面是an answer I wrote before.的一个有点编辑的版本我认为这次我做了更好的措辞。
答案 1 :(得分:7)
我相信您想要的一般形式是repr()
或对象的__repr__()
方法。
关于__repr__()
:
由repr()内置函数调用 并通过字符串转换(反向 引用)计算“官方” 对象的字符串表示。
请参阅此处的文档:object.repr(self)
答案 2 :(得分:3)
def foo1():
x = 5
y = 4
z = x
print names_of1(x, locals())
def names_of1(var, callers_namespace):
return [name for (name, value) in callers_namespace.iteritems() if var is value]
foo1() # prints ['x', 'z']
如果您正在使用具有堆栈帧支持的Python(大部分都支持CPython),则不需要将locals dict传递给names_of
函数;该函数可以从其调用者的框架本身检索该字典:
def foo2():
xx = object()
yy = object()
zz = xx
print names_of2(xx)
def names_of2(var):
import inspect
callers_namespace = inspect.currentframe().f_back.f_locals
return [name for (name, value) in callers_namespace.iteritems() if var is value]
foo2() # ['xx', 'zz']
如果您正在使用可以为其指定名称属性的值类型,则可以为其指定名称,然后使用该类型:
class SomeClass(object):
pass
obj = SomeClass()
obj.name = 'obj'
class NamedInt(int):
__slots__ = ['name']
x = NamedInt(321)
x.name = 'x'
最后,如果您正在使用类属性并且希望它们知道它们的名称(描述符是明显的用例),那么您可以像使用Django ORM和SQLAlchemy声明式样式那样使用元类编程做很酷的技巧表定义:
class AutonamingType(type):
def __init__(cls, name, bases, attrs):
for (attrname, attrvalue) in attrs.iteritems():
if getattr(attrvalue, '__autoname__', False):
attrvalue.name = attrname
super(AutonamingType,cls).__init__(name, bases, attrs)
class NamedDescriptor(object):
__autoname__ = True
name = None
def __get__(self, instance, instance_type):
return self.name
class Foo(object):
__metaclass__ = AutonamingType
bar = NamedDescriptor()
baaz = NamedDescriptor()
lilfoo = Foo()
print lilfoo.bar # prints 'bar'
print lilfoo.baaz # prints 'baaz'
答案 3 :(得分:1)
有三种方法可以在python中获取对象的“字符串”表示形式: 1:str()
>>> foo={"a":"z","b":"y"}
>>> str(foo)
"{'a': 'z', 'b': 'y'}"
2:repr()
>>> foo={"a":"z","b":"y"}
>>> repr(foo)
"{'a': 'z', 'b': 'y'}"
3:字符串插值:
>>> foo={"a":"z","b":"y"}
>>> "%s" % (foo,)
"{'a': 'z', 'b': 'y'}"
在这种情况下,所有三种方法都生成相同的输出,区别在于str()调用dict.__str__()
,而repr()调用dict.__repr__()
。 str()用于字符串插值,而当列表或字典打印时,Python内部对列表或字典中的每个对象使用repr()。
正如Tendayi Mawushe上面提到的,由repr制作的字符串不一定是人类可读的。
此外,.__str__()
的默认实现是调用.__repr__()
,因此如果该类没有自己覆盖.__str__()
,则.__repr__()
返回的值为使用