我怎么强调都不过分……拜托,拜托,仅将其用于教育目的。它易碎、不可靠... 糟糕如果您更改代码中的任何内容,它就会停止工作。这东西好脏。它可能是不可携带的……天哪……我想当我点击 Post Your Answer
时有几只小猫被杀了
import inspect
import re
class Foo(object):
def __init__(self):
r = re.compile(
r"\W+['\"](?P<name>\w+)['\"]\W+%s\W+"
% self.__class__.__name__
)
caller_frame = inspect.currentframe().f_back
code_context = inspect.getframeinfo(caller_frame).code_context
match = r.match(''.join(code_context))
if match:
self.name = match.groupdict()['name']
print "Assigned name: %s" % self.name
else:
raise Exception("This wasn't called as it was supposed to")
if __name__ == "__main__":
foo_dict = {
'foo1': Foo(),
'foo2': Foo(),
}
但它似乎满足您的要求:
borrajax@borrajax:/tmp$ python ./test.py
Assigned name: foo1
Assigned name: foo2
现在,我要做的是:
选项 1:
在初始化时传递名称。
可能是最简单、最可维护的,并且使代码处于更清晰的状态(如果其他人阅读您的代码,这一点很重要)
class Foo(object):
def __init__(self, name):
self.name = name
print "Assigned name: %s" % self.name
if __name__ == "__main__":
foo_dict = {
'foo1': Foo('foo1'),
'foo2': Foo('foo2'),
}
选项 2:
创建您自己的dict 类并覆盖__setitem__ 方法(另请参阅Subclassing Python dictionary to override __setitem__ 和How to "perfectly" override a dict?):
class Foo(object):
pass
class MyDict(dict):
def __setitem__(self, key, val):
if not isinstance(val, Foo):
raise TypeError("My dict only accepts %s" % Foo)
val.name = key
print "Assigned name: %s" % val.name
return super(MyDict, self).__setitem__(key, val)
if __name__ == "__main__":
foo_dict = MyDict()
foo_dict['foo1'] = Foo()
foo_dict['foo2'] = Foo()
foo_dict['foo3'] = 1
打印:
borrajax@borrajax:/tmp$ python ./test.py
Assigned name: foo1
Assigned name: foo2
Traceback (most recent call last):
File "./stack64.py", line 17, in <module>
foo_dict['foo3'] = 1
File "./stack64.py", line 8, in __setitem__
raise TypeError("My dict only accepts %s" % Foo)
TypeError: My dict only accepts <class '__main__.Foo'>
这样做的缺点是神奇地在分配给字典时将属性(.name)添加到 Foo 的实例中,这可能会导致名称冲突(如果您的 Foo 类已经有一个.name,这个方法会改变它的值)。一般来说,我会远离那些在执行过程中神奇地为实例添加属性的方法。
选项 3:
使用@Daniel 的answer 回答这个问题。其他人阅读您的代码时清晰易懂。