我希望迭代类中的方法,或者根据存在的方法以不同方式处理类或实例对象。我如何获得类方法列表?
另见:
答案 0 :(得分:275)
示例(列出optparse.OptionParser
类的方法):
>>> from optparse import OptionParser
>>> import inspect
>>> inspect.getmembers(OptionParser, predicate=inspect.ismethod)
[([('__init__', <unbound method OptionParser.__init__>),
...
('add_option', <unbound method OptionParser.add_option>),
('add_option_group', <unbound method OptionParser.add_option_group>),
('add_options', <unbound method OptionParser.add_options>),
('check_values', <unbound method OptionParser.check_values>),
('destroy', <unbound method OptionParser.destroy>),
('disable_interspersed_args',
<unbound method OptionParser.disable_interspersed_args>),
('enable_interspersed_args',
<unbound method OptionParser.enable_interspersed_args>),
('error', <unbound method OptionParser.error>),
('exit', <unbound method OptionParser.exit>),
('expand_prog_name', <unbound method OptionParser.expand_prog_name>),
...
]
请注意getmembers
返回2元组列表。第一项是成员的名称,第二项是值。
您还可以将实例传递给getmembers
:
>>> parser = OptionParser()
>>> inspect.getmembers(parser, predicate=inspect.ismethod)
...
答案 1 :(得分:169)
有dir(theobject)
方法列出对象的所有字段和方法(作为元组)和inspect模块(作为代码写),用文档列出字段和方法(在“”中) )。
因为在Python中可能会调用所有(甚至是字段),所以我不确定是否有内置函数只列出方法。您可能想要尝试通过dir
的对象是否为callable。
答案 2 :(得分:73)
没有外部库的Python 3.x答案
method_list = [func for func in dir(Foo) if callable(getattr(Foo, func))]
被排除在外的结果:
method_list = [func for func in dir(Foo) if callable(getattr(Foo, func)) and not func.startswith("__")]
答案 3 :(得分:27)
尝试使用属性__dict__
。
答案 4 :(得分:15)
您还可以从类型中导入FunctionType并使用class.__dict__
:
from types import FunctionType
class Foo:
def bar(self): pass
def baz(self): pass
def methods(cls):
return [x for x, y in cls.__dict__.items() if type(y) == FunctionType]
methods(Foo) # ['bar', 'baz']
答案 5 :(得分:12)
请注意,您需要考虑是否需要结果中包含的继承(但未覆盖)的基类方法。 dir()
和inspect.getmembers()
操作确实包含基类方法,但使用__dict__
属性则不行。
答案 6 :(得分:11)
说您想知道与列表类相关的所有方法 只需输入以下
print (dir(list))
上面将为您提供列表类的所有方法
答案 7 :(得分:9)
您可以使用以下代码列出python类中的所有方法
dir(className)
这将返回类中所有方法名称的列表
答案 8 :(得分:3)
试试
print(help(ClassName))
它打印出类的方法
答案 9 :(得分:3)
有这种方法:
[getattr(obj, m) for m in dir(obj) if not m.startswith('__')]
在处理类 instance 时,也许最好返回带有方法引用的列表,而不仅仅是名称¹。如果这是您的目标,以及
import
__init__
)它可能有用。您可能还需要确保它是callable(getattr(obj, m))
,因为dir
返回obj
中的所有属性,而不仅仅是方法。
简而言之,对于像这样的类
class Ghost:
def boo(self, who):
return f'Who you gonna call? {who}'
我们可以使用以下方式检查实例检索
>>> g = Ghost()
>>> methods = [getattr(g, m) for m in dir(g) if not m.startswith('__')]
>>> print(methods)
[<bound method Ghost.boo of <__main__.Ghost object at ...>>]
因此您可以立即调用它:
>>> for method in methods:
... print(method('GHOSTBUSTERS'))
...
Who you gonna call? GHOSTBUSTERS
¹一个用例:
我将其用于单元测试。有一堂课,所有方法都执行同一过程的变体-这导致了冗长的测试,每种方法之间只有一个小小的调整。 DRY是一个遥远的梦想。
我应该对所有方法进行一次测试,所以我进行了上述迭代。
尽管我意识到我反而应该将代码本身重构为DRY兼容的……这在将来仍然可能会成为一个挑剔的灵魂。
答案 10 :(得分:2)
我只是将其保留在这里,因为评价最高的答案尚不清楚。
这是一个简单的测试,不是基于Enum的普通类。
# -*- coding: utf-8 -*-
import sys, inspect
from enum import Enum
class my_enum(Enum):
"""Enum base class my_enum"""
M_ONE = -1
ZERO = 0
ONE = 1
TWO = 2
THREE = 3
def is_natural(self):
return (self.value > 0)
def is_negative(self):
return (self.value < 0)
def is_clean_name(name):
return not name.startswith('_') and not name.endswith('_')
def clean_names(lst):
return [ n for n in lst if is_clean_name(n) ]
def get_items(cls,lst):
try:
res = [ getattr(cls,n) for n in lst ]
except Exception as e:
res = (Exception, type(e), e)
pass
return res
print( sys.version )
dir_res = clean_names( dir(my_enum) )
inspect_res = clean_names( [ x[0] for x in inspect.getmembers(my_enum) ] )
dict_res = clean_names( my_enum.__dict__.keys() )
print( '## names ##' )
print( dir_res )
print( inspect_res )
print( dict_res )
print( '## items ##' )
print( get_items(my_enum,dir_res) )
print( get_items(my_enum,inspect_res) )
print( get_items(my_enum,dict_res) )
这是输出结果。
3.7.7 (default, Mar 10 2020, 13:18:53)
[GCC 9.2.1 20200306]
## names ##
['M_ONE', 'ONE', 'THREE', 'TWO', 'ZERO']
['M_ONE', 'ONE', 'THREE', 'TWO', 'ZERO', 'name', 'value']
['is_natural', 'is_negative', 'M_ONE', 'ZERO', 'ONE', 'TWO', 'THREE']
## items ##
[<my_enum.M_ONE: -1>, <my_enum.ONE: 1>, <my_enum.THREE: 3>, <my_enum.TWO: 2>, <my_enum.ZERO: 0>]
(<class 'Exception'>, <class 'AttributeError'>, AttributeError('name'))
[<function my_enum.is_natural at 0xb78a1fa4>, <function my_enum.is_negative at 0xb78ae854>, <my_enum.M_ONE: -1>, <my_enum.ZERO: 0>, <my_enum.ONE: 1>, <my_enum.TWO: 2>, <my_enum.THREE: 3>]
那我们有什么:
dir
提供的数据不完整inspect.getmembers
提供的数据不完整,并提供getattr()
无法访问的内部密钥__dict__.keys()
提供完整而可靠的结果 为什么投票如此错误?而我错了吗?还有其他答案得票数太低的人呢?
答案 11 :(得分:1)
def find_defining_class(obj, meth_name):
for ty in type(obj).mro():
if meth_name in ty.__dict__:
return ty
所以
print find_defining_class(car, 'speedometer')
Think Python第210页
答案 12 :(得分:1)
这也有效:
mymodule.py
def foo(x)
return 'foo'
def bar()
return 'bar'
在另一个文件中
import inspect
import mymodule
method_list = [ func[0] for func in inspect.getmembers(mymodule, predicate=inspect.isroutine) if callable(getattr(mymodule, func[0])) ]
输出:
['foo', 'bar']
来自python文档:
inspect.isroutine(对象)
Return true if the object is a user-defined or built-in function or method.
答案 13 :(得分:1)
您可以使用我创建的功能。
def method_finder(classname):
non_magic_class = []
class_methods = dir(classname)
for m in class_methods:
if m.startswith('__'):
continue
else:
non_magic_class.append(m)
return non_magic_class
method_finder(list)
输出:
['append',
'clear',
'copy',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']
答案 14 :(得分:0)
以上都不适合我。
我在编写 pytests 时遇到了这个问题。
我发现的唯一解决方法是:
1- 创建另一个目录并将我所有的 .py 文件放在那里
2- 为我的 pytests 创建一个单独的目录,然后导入我感兴趣的类
这使我能够获得类中的最新方法 - 您可以更改方法名称,然后使用 print(dir(class))
进行确认。
答案 15 :(得分:0)
要生成方法列表,请将方法名称放入没有常规括号的列表中。删除名称并附加括号并调用该方法。
def methodA():
print("@ MethodA")
def methodB():
print("@ methodB")
a = []
a.append(methodA)
a.append(methodB)
for item in a:
item()
答案 16 :(得分:0)
str
给出与...相同的列表
methods = [(func, getattr(o, func)) for func in dir(o) if callable(getattr(o, func))]
确实。
答案 17 :(得分:-1)
如果您只想列出python类的方法
import numpy as np
print(np.random.__all__)
答案 18 :(得分:-1)
我知道这是一篇很老的帖子,但是只是写了这个函数,并且会留下这个例子,有人会绊倒寻找答案:
def classMethods(the_class,class_only=False,instance_only=False,exclude_internal=True):
def acceptMethod(tup):
#internal function that analyzes the tuples returned by getmembers tup[1] is the
#actual member object
is_method = inspect.ismethod(tup[1])
if is_method:
bound_to = tup[1].im_self
internal = tup[1].im_func.func_name[:2] == '__' and tup[1].im_func.func_name[-2:] == '__'
if internal and exclude_internal:
include = False
else:
include = (bound_to == the_class and not instance_only) or (bound_to == None and not class_only)
else:
include = False
return include
#uses filter to return results according to internal function and arguments
return filter(acceptMethod,inspect.getmembers(the_class))
答案 19 :(得分:-2)
这只是一个观察。 “编码”似乎是字符串对象的一种方法
str_1 = 'a'
str_1.encode('utf-8')
>>> b'a'
但是,如果检查str1中的方法,则会返回一个空列表
inspect.getmember(str_1, predicate=inspect.ismethod)
>>> []
所以,也许我错了,但是问题似乎并不简单。
答案 20 :(得分:-2)
class CPerson:
def __init__(self, age):
self._age = age
def run(self):
pass
@property
def age(self): return self._age
@staticmethod
def my_static_method(): print("Life is short, you need Python")
@classmethod
def say(cls, msg): return msg
test_class = CPerson
# print(dir(test_class)) # list all the fields and methods of your object
print([(name, t) for name, t in test_class.__dict__.items() if type(t).__name__ == 'function' and not name.startswith('__')])
print([(name, t) for name, t in test_class.__dict__.items() if type(t).__name__ != 'function' and not name.startswith('__')])
输出
[('run', <function CPerson.run at 0x0000000002AD3268>)]
[('age', <property object at 0x0000000002368688>), ('my_static_method', <staticmethod object at 0x0000000002ACBD68>), ('say', <classmethod object at 0x0000000002ACF0B8>)]
答案 21 :(得分:-2)
如果您的方法是&#34;常规&#34;方法而不是statimethod
,classmethod
等
我想出了一点点黑客 -
for k, v in your_class.__dict__.items():
if "function" in str(v):
print(k)
通过更改&#34; function&#34;可以将其扩展到其他类型的方法。相应地处于if
条件
在python 2.7上测试。