如何从__getattr__
函数中获取类函数列表?
Python v2.7,如果重要的话。
尝试在dir
中使用__getattr__
会导致无限递归。
class Hal(object):
def __getattr__(self, name):
print 'I don\'t have a %s function' % name
names = dir(self) # <-- infinite recursion happens here
print 'My functions are: %s' % ', '.join(names)
exit()
def close_door(self):
pass
x = Hal()
x.open_door()
这是我想要的输出:
I don't have a open_door function
My functions are: close_door, __getattr__, __init__, __doc__, ...
任何其他能让我得到我想要的输出的解决方案都能正常工作。我想在一个函数不存在的情况下进行模糊字符串匹配,以试图建议用户可能有什么意思。
答案 0 :(得分:2)
names = self.__class__.__dict__
可能?
>>> class A:
... def hello(self,x):
... print "hello ",x
... def my_dir(self):
... print self.__class__.__dict__
...
>>> A().my_dir()
{'__module__': '__main__', 'my_dir': <function my_dir at 0x029A5AB0>, 'hello': <
function hello at 0x029A5CB0>, '__doc__': None}
答案 1 :(得分:2)
你有什么理由不能这样做吗?
names = dir(self.__class__)
您是否希望消费者扩展Hal的实例以获得自定义方法?
如果您只想要实现的方法,但没有列出内置插件,您也可以尝试这样做:
names = [prop for prop in dir(self.__class__) if prop[1] != "_"]
答案 2 :(得分:2)
我认为这是有效的:
import types
class Hal(object):
def __getattr__(self, name):
print ('I don\'t have a %s function' % name)
funcs = (name for name,func in self.__class__.__dict__.items() if isinstance(func,types.FunctionType))
#names = dir(self) # <-- infinite recursion happens here
print ('My functions are: %s' % ', '.join(str(f) for f in funcs))
exit()
@staticmethod
def foo():
pass
@classmethod
def bar(cls):
pass
def qux(self):
pass
def close_door(self):
pass
x = Hal()
x.foo = 'bar'
x.open_door()
答案 3 :(得分:0)
一种解决方案是在添加dir
方法之前制作__getattr__
的副本:
class Hal(object):
def __init__(self):
self._names = dir(self)
def __getattr__(self, name):
print self.names
self.__getattr__ = __getattr__
但是,对于简单的情况,您只需在类对象上调用dir
(以及同样getattr
或inspect.getmembers
或其他)来解决问题。如果实例可以在构造之后添加方法,则这不起作用,但如果这不是问题,则很容易:
names = dir(self.__class__)
但是你得到名字,过滤方法,有几件事要做。
首先,您可以在isinstance
上使用getattr(self, name)
并确保它是方法包装器(或获取绑定版本的类型并确保它是实例方法)。如果您直接从self.__class__.__dict__
获取值,则不会得到完全相同的内容,就像您以自己喜欢的方式获取名称并拨打getattr(self, name)
或getattr(self.__class__, name)
一样。特别是,实例方法将显示为function
,它比方法包装器更容易测试。虽然其他一些案件现在更难以发现。
无论如何,基于类型的任何东西都不会找到像方法那样但不是的东西(例如,因为你已经直接为对象分配了一个内置函数,在某些类型的装饰器中包装了一些东西,书面自定义描述符,使用具有__callable__
方法的类作为函数,等等。如果你正在做任何花哨的事情(或担心有人可能会在以后添加一些奇特的东西),你真的需要测试你是否可以显式绑定成员(或伪造它绑定到None
),然后检查是否结果是callable
,然后可能进行进一步的测试以确保它可以正确调用(因为否则你会被@staticmethod
和类似的东西所欺骗。真的,如果出现这种情况(并且你真的想过你的设计并且说服自己和至少一个其他人并不疯狂......),你应该测试你能想到的每一个案例......
如果你想知道方法是在Hal
中定义的还是实例而不是object
或其他基类,有几种方法可以做到这一点,但最简单的方法是减去基类的成员。 (当然,如果你不关心实例中定义的方法,Hal.__dict__
已经拥有了你想要的东西。)