在类的 __init__() 中获取实例名称

25 投票
10 回答
73136 浏览
提问于 2025-04-15 15:45

在用Python创建一个新的类对象时,我想根据类的实例名称来设置一个默认值,而不需要额外传入参数。我该怎么做呢?下面是我尝试的基本伪代码:

class SomeObject():
    defined_name = u""

    def __init__(self, def_name=None):
        if def_name == None:
            def_name = u"%s" % (<INSTANCE NAME>)
        self.defined_name = def_name

ThisObject = SomeObject()
print ThisObject.defined_name   # Should print "ThisObject"

10 个回答

11

你可以在你的类里面创建一个方法,这个方法会检查当前环境中的所有变量,并使用 hash() 来查找 self 变量。

这里提供的解决方案会返回所有指向实例对象的变量。

在下面的类中,使用了 isinstance() 来避免在使用 hash() 时出现问题,因为有些对象,比如 numpy.array 或者 list,是不能被哈希的。

import inspect
class A(object):
    def get_my_name(self):
        ans = []
        frame = inspect.currentframe().f_back
        tmp = dict(frame.f_globals.items() + frame.f_locals.items())
        for k, var in tmp.items():
            if isinstance(var, self.__class__):
                if hash(self) == hash(var):
                    ans.append(k)
        return ans

接下来进行了以下测试:

def test():
    a = A()
    b = a
    c = b
    print c.get_my_name()

结果是:

test()
#['a', 'c', 'b']
29

好吧,几乎有一种方法可以做到这一点:

#!/usr/bin/env python
import traceback
class SomeObject():
    def __init__(self, def_name=None):
        if def_name == None:
            (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
            def_name = text[:text.find('=')].strip()
        self.defined_name = def_name

ThisObject = SomeObject()
print ThisObject.defined_name 
# ThisObject

traceback模块可以让你查看调用SomeObject()时用到的代码。通过一些字符串处理,比如用text[:text.find('=')].strip(),你可以猜测出def_name应该是什么。

不过,这种方法不太稳定。例如,这种情况下效果就不好:

ThisObject,ThatObject = SomeObject(),SomeObject()
print ThisObject.defined_name
# ThisObject,ThatObject
print ThatObject.defined_name 
# ThisObject,ThatObject

所以如果你打算用这个方法,你得记住,调用SomeObject()时必须用简单的Python语句:

ThisObject = SomeObject()

顺便说一下,作为使用traceback的进一步示例,如果你定义了

def pv(var):
    # stack is a list of 4-tuples: (filename, line number, function name, text)
    # see http://docs.python.org/library/traceback.html#module-traceback
    #
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    # ('x_traceback.py', 18, 'f', 'print_var(y)')
    print('%s: %s'%(text[text.find('(')+1:-1],var))

那么你可以调用

x=3.14
pv(x)
# x: 3.14

来打印出变量名和它的值。

24

实例是没有名字的。当全局名字 ThisObject 被绑定到通过运行 SomeObject 这个构造函数创建的实例时,构造函数已经执行完毕了。

如果你想给一个对象起个名字,只需要在构造函数中把名字传进去就可以了。

def __init__(self, name):
    self.name = name

撰写回答