Python对象方法字典
我需要一个类的实例变量,这个变量里要存放一些处理器(也就是这个类实例里指定的方法)。这些处理器的列表可以在需要的时候提供。
我有两个解决方案,但都不太合适。
- http://www.ideone.com/3aSkT - 这个方案会出现循环引用的问题。虽然垃圾回收(GC)可以清理它,但我们不知道具体什么时候会清理。
- http://www.ideone.com/OaP5c - 在这个方案中,当你调用时,需要明确地把类的实例传递给函数。
还有其他建议吗?
3 个回答
在这里,我要扩展一下@mac的回答,因为提问者想要了解一个类的实例变量,并且他可能还想获取关于“私有”方法的信息:
In [5]: class Foo(object):
...: def m1(self):pass
...: def m2(self):pass
...:
In [6]: f = Foo()
In [7]: lst = dir(f)
In [8]: [m for m in lst if not m.endswith('__')]
Out[8]: ['m1', 'm2']
如果你想要对象的方法:
In [17]: getattr(Foo, 'm1')
Out[17]: <unbound method Foo.m1>
或者直接在实例的列表推导中:
In [18]: [getattr(f, m) for m in lst if not m.endswith('__')]
Out[18]:
[<bound method Foo.m1 of <__main__.Foo object at 0x00000000073DD1D0>>,
<bound method Foo.m2 of <__main__.Foo object at 0x00000000073DD1D0>>]
编辑:根据你在链接中给出的例子,也许你在寻找类似这样的东西:
class SomeClass:
store = {0: 'someMethod', 1: 'someMethod1'}
def __init__(self):
print('__init__')
def __del__(self):
print('__del__')
def get_dict(self):
return [getattr(self, att) for idx, att in SomeClass.store.items()]
def someMethod(): pass
def someMethod1(): pass
f = SomeClass()
print f.get_dict()
这将打印出:
__init__
[<bound method SomeClass.someMethod of <__main__.SomeClass instance at 0x0000000
0026E2E08>>, <bound method SomeClass.someMethod1 of <__main__.SomeClass instance
at 0x00000000026E2E08>>]
__del__
我不太明白你的问题,但如果你想把方法名“映射”到其他方法上(比如调用 Foo().store()
实际上会调用 Foo().someMethod()
),而不直接引用它们,你可以通过重写默认的 object.__getattribute__
行为来实现。
class Foo(object):
mapping = {'store': 'someMethod'}
def __getattribute__(self, attr):
try:
# first check if it's a "regular" attribute/method
return super(Foo, self).__getattribute__(attr)
except AttributeError:
# attribute was not found, if it's not in your mapping, re-raise the error
if attr not in self.mapping:
raise
mapped_attr = self.mapping[attr]
return super(Foo, self).__getattribute__(mapped_attr)
def someMethod(self):
print "Foo().someMethod()"
foo = Foo()
foo.store()
输出:
>>> Foo().someMethod()
如果我理解得没错,你可以直接使用内置的函数 dir()
。举个例子:
>>> class Foo(object):
... def m1(self):
... pass
... def m2(self):
... pass
...
>>> dir(Foo)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm1', 'm2']
>>> [m for m in dir(Foo) if '__' not in m]
['m1', 'm2']
补充:你的问题和评论不是很清楚。如果你能编辑一下你的问题,说明你期望的结果,那会更有帮助。我猜,看到你下面的评论("我需要这个字典 {int type: method type}
"),你可能想要的是:
>>> dict(enumerate([getattr(Foo, m) for m in dir(Foo) if '__' not in m]))
{0: <unbound method Foo.m1>, 1: <unbound method Foo.m2>}
补充2:看了你最新的代码片段,当你写:
packet_ids_to_check_up = (0x0404, 0x0405, 0x0404, 0x0505, 0x0506)
for packet_id in packet_ids_to_check_up:
if packet_id in some_class_obj:
some_class_obj[packet_id]('Hello world')
看起来你希望你的类能像字典一样工作。如果是这样的话,你可能应该看看 collections.abc
模块,特别是 MutableMapping
类。从 Python 词汇表 中可以了解到:
映射 - 一种容器对象,支持任意键的查找,并实现了映射或可变映射抽象基类中指定的方法。例子包括 dict、collections.defaultdict、collections.OrderedDict 和 collections.Counter。
这意味着你需要实现以下方法:
__contains__
keys
items
values
get
__eq__
__ne__
pop
popitem
clear
update
setdefault
不过,从你的代码来看,似乎并不明显为什么你不能直接使用一个简单的字典(或者直接继承 dict
...)。
这样说清楚了吗?