在类的 __init__() 中获取实例名称
在用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