簡體   English   中英

python是否允許從實例方法調用實例變量名稱?

[英]Does python allow calling of an instance variable name from an instance method?

我想知道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

引發異常。 這不僅是發出錯誤信號的適當方法,而且對於調試也更有用。 追溯不僅包括執行方法調用的行,還包括其他行,行號,函數名等,它們對於調試而言比變量名更有用。 例:

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和好友)。

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()。 在list 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中執行此操作。

我說的是沉重的,不是笨拙的,順便說一句,我認為它不是笨拙的。

不,你不能。 對象可以具有任意數量的名稱,因此該問題甚至沒有任何意義。 考慮:

a1 = a2 = a3 = A()

A()實例的名稱是什么?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM