0

我想知道python中是否有一种方法可以调用实例变量的名称?例如,如果我定义一个类

>>>class A(object):
...    def get_instance_name(self):
...        return # The name of the instance variable
>>>obj = A()
>>>obj.get_instance_name()
obj
>>>blah = A()
>>>blah.get_instance_name()
blah
4

3 回答 3

3

引发异常。它不仅是发出错误信号的适当方式,而且对于调试也更有用。回溯包括进行方法调用的行,还包括附加的行、行号、函数名等,这些对调试来说比变量名更有用。例子:

class A:
    def do(self, x):
        if x < 0:
            raise ValueError("Negative x")

def wrong(a, x):
   a.do(-x)

wrong(A(), 1)

如果未捕获到异常,这将提供与此类似的回溯:

Traceback (most recent call last):
  File "...", line 1, in <module>
    wrong(A(), 1)
  File "...", line 7, in wrong
    a.do(-x)
  File "...", line 4, in do
    raise ValueError("Negative x")
ValueError: Negative x

traceback即使没有例外(print_stack和朋友) ,您也可以使用该模块以编程方式获取此信息。

于 2013-07-12T17:33:17.280 回答
1

globals()返回一个表示模块命名空间的字典(命名空间不是这个字典,后者只代表它)

class A(object):
    def get_instance_name(self):
        for name,ob in globals().iteritems():
            if ob is self:
                return name
       
obj = A()
print obj.get_instance_name()

blah = A()
print blah.get_instance_name()

tu = (obj,blah)
print [x.get_instance_name() for x in tu]

结果

obj
blah
['obj', 'blah']

.

编辑

考虑到这些言论,我写了这个新代码:

class A(object):

    def rondo(self,nameinst,namespace,li,s,seen):
        for namea,a in namespace.iteritems():
            if a is self:
                li.append(nameinst+s+namea)
                
            if namea=='__builtins__':
                #this condition prevents the execution to go
                # in the following section elif, so that self
                # isn't searched among the cascading attributes
                # of the builtin objects and the attributes.
                # This is to avoid to explore all the big tree
                # of builtin objects and their cascading attributes.
                # It supposes that every builtin object has not
                # received the instance, of which the names are
                # searched, as a new attribute. This makes sense.
                for bn,b in __builtins__.__dict__.iteritems():
                    if b is self:
                        li.append(nameinst+'-'+b)
            elif hasattr(a,'__dict__') \
                 and not any(n+s+namea in seen for n in seen)\
                 and not any(n+s+namea in li for n in li):
                seen.append(nameinst+s+namea)
                self.rondo(nameinst+s+namea,a.__dict__,li,'.')
            else:
                seen.append(nameinst+s+namea)
            
    def get_instance_name(self):
        li = []
        seen = []
        self.rondo('',globals(),li,'')
        return li if li else None

与以下

bumbum = A()
blah = A()

print "bumbum's names:\n",bumbum.get_instance_name()

print "\nmap(lambda y:y.get_instance_name(), (bumbum,blah) :\n",map(lambda y:y.get_instance_name(), (bumbum,blah))

print "\n[y.get_instance_name() for y in (bumbum,blah)] :\n",[y.get_instance_name() for y in (bumbum,blah)]

结果是

bumbum's names:
['bumbum']

map(lambda y:y.get_instance_name(), (bumbum,blah) :
[['bumbum'], ['blah']]

[y.get_instance_name() for y in (bumbum,blah)] :
[['bumbum', 'y'], ['blah', 'y']]

第二个列表理解表明函数 get_instance_name() 必须小心使用。在列表 comp 中,标识符y依次分配给 (bumbum,blah) 的每个元素,然后函数将其作为实例的名称找出来!

.

现在,一个更复杂的情况:

ahah = A() # ahah : first name for this instance

class B(object):
    pass

bobo = B()
bobo.x = ahah # bobo.x : second name for ahah
jupiter = bobo.x # jupiter : third name for ahah

class C(object):
    def __init__(self):
        self.azerty = jupiter # fourth name for ahah
    
ccc = C()  
kkk = ccc.azerty # kkk : fifth name for ahah

bobo.x.inxnum = 1005
bobo.x.inxwhat = kkk # bobo.x.inxwhat : fifth name for ahah
# Since bobo.x is instance ahah, this instruction also
# creates attribute inxwhat in ahah instance's __dict__ .
# Consequently, instance ahah having already 5 names, 
# this instruction adds 5 additional names, each one
#  ending with .inxwhat
# By the way, this kkk being ahah itself, it results that ahah
# is the value of its own attribute inxwhat.

print ahah.get_instance_name()

结果

['bobo.x', 'bobo.x.inxwhat', 
 'ahah', 'ahah.inxwhat', 
 'jupiter', 'jupiter.inxwhat', 
 'kkk', 'kkk.inxwhat', 
 'ccc.azerty', 'ccc.azerty.inxwhat']

我同意判断这个解决方案有点重,如果编码人员认为他需要这么重的函数,可能是因为算法不是最优的。但我发现有趣的是,虽然看起来并不明显,但可以在 Python 中执行此操作。

我说沉重,而不是 hacky,顺便说一句,我不觉得它是 hacky。

于 2013-07-12T17:32:34.053 回答
0

不,你不能。对象可以有任意数量的名称,所以这个问题甚至没有意义。考虑:

a1 = a2 = a3 = A()

A() 的实例名称是什么?

于 2013-07-12T17:50:22.453 回答