파이썬 클래스에서 메소드 목록을 어떻게 얻습니까?


330

1
소스 ..... 소스 ...
RickyA

4
@JonCrowell 그것은 힘이 작동하는 방식이 아닙니다.
Ken Williams

컴파일러 지시어를 사용하는 Cython의 경우 binding: stackoverflow.com/a/46041480/1959808
Ioannis Filippidis

4
python3에서 : [f for f in dir(ClassName) if not f.startswith('_')]또는 dir(ClassName)모든 것을 위해
Seraf

@Seraf 댓글에 답을 올리지 마십시오. 대신 답변을 게시하십시오.
wjandrea

답변:


332

예제 ( optparse.OptionParser클래스 의 메소드 나열 ) :

>>> from optparse import OptionParser
>>> import inspect
#python2
>>> 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>),
 ...
 ]
# python3
>>> inspect.getmembers(OptionParser, predicate=inspect.isfunction)
...

getmembers2- 튜플 목록 을 반환합니다. 첫 번째 항목은 멤버의 이름이고 두 번째 항목은 값입니다.

인스턴스를 getmembers다음으로 전달할 수도 있습니다 .

>>> parser = OptionParser()
>>> inspect.getmembers(parser, predicate=inspect.ismethod)
...

4
완벽한 술어 부분이 핵심입니다. 그렇지 않으면 여분의 메타 정보가있는 dict 과 동일한 것을 얻습니다 . 감사.
Purrell

2
클래스의 모든 메소드 목록 (다른 클래스에서 상속 된 메소드 포함)을 생성합니까, 아니면 해당 클래스에 명시 적으로 정의 된 메소드 만 나열합니까?
Anderson Green

10
inspect.isroutine더 적합한 술어 일 수 있습니다. inspect.ismethod모든 객체의 메소드에서 작동하지는 않습니다.
Gavin S. Yancey

1
이것은 클래스의 인스턴스를 사용할 때만 작동했습니다 (예와 마찬가지로). 이것이 예상되는 동작입니까?
Christian Reall-Fluharty 2018 년

2
파이썬 3.7에서는 적어도 작동하지 않습니다. 클래스를 인스턴스화해야합니다
kederrac

222

거기입니다 dir(theobject)목록의 모든 필드와 (튜플)를 개체의 메서드에 대한 방법과는 ( "" "에서) 자신의 의사와 필드와 방법을 나열 (codeape 쓰기로) 모듈을 검사합니다.

파이썬에서 모든 필드 (짝수 필드)가 호출 될 수 있기 때문에 메소드 만 나열하는 내장 함수가 있는지 확실하지 않습니다. 통과 하는 객체dir호출 가능한지 여부를 시도 할 수 있습니다 .


3
dir (object)는 내가 사용한 가장 간단한 솔루션입니다.
lstodd

@skjerns 입력하려면 5 개의 기호가 필요합니다. :)
Dr_Zaszuś

117

외부 라이브러리가없는 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("__")]

38

list class와 관련된 모든 메소드를 알고 싶다고 가정하십시오.

 print (dir(list))

위의 목록 클래스의 모든 방법을 제공합니다


2
이것이 최선의 해결책입니다
Zeeshan Ahmad

3
print([ m for m in dir(my_class) if not m.startswith('__')])
Evhz

32

속성을 사용해보십시오 __dict__.


16
나는 당신이 dict 을 의미한다고 생각합니다 . 그러나 그것은 메소드가 아닌 인스턴스의 속성을 나열합니다.
me_and December

1
… 나에게도 효과가 없었습니다. Markdown 구문을 살펴본 결과 __dict__를 의미한다고 생각합니다.
me_and December

3
@me_and 아마도 "self .__ dict__"를 수행하거나보다 일반적으로 인스턴스 버전을 호출하는 것입니다 __dict__. 그러나 클래스 __dict__도 있고 클래스 메소드를 표시해야합니다 :)
Seaux

21

유형에서 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']

이것은 나를 위해 잘 작동했습니다. 의 및 개인 메소드 and not x.startswith('_')를 무시하는 데 사용하기 위해 목록 이해의 끝에 추가 했습니다 __init__.
Christopher Pearson

2
당신은 제거 할 수 importFunctionType와 모함 람다를 사용하여 type():type(lambda:0)
Tersosauros

isinstancetype(y) == FunctionType여기 보다 낫습니다 .
Gloweye

13

상속 된 (하지만 재정의되지는 않은) 기본 클래스의 메소드가 결과에 포함되는지 여부를 고려해야합니다. dir()inspect.getmembers()작업은 기본 클래스 메소드를 포함 할 수 있지만, 사용 __dict__속성은하지 않습니다.


3

이것은 또한 작동합니다 :

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']

파이썬 문서에서 :

inspect.isroutine (객체)

Return true if the object is a user-defined or built-in function or method.

2
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') 

파이썬 페이지 210 생각


3
5의 들여 쓰기? 키워드를 대문자로 사용 하시겠습니까? 비 pep8 스타일 간격?
Florrie

1
한 번 코딩 컨벤션 나치가 그것을 얻지 못했습니다!
rbennell

1
이 질문에 어떻게 대답합니까?
Aran-Fey

2

이 방법이 있습니다 :

[getattr(obj, m) for m in dir(obj) if not m.startswith('__')]

클래스 인스턴스를 다룰 때 아마도 이름 ¹ 대신 메소드 참조가있는 목록을 반환하는 것이 좋습니다. 그것이 당신의 목표라면

  1. 아니 사용 import
  2. __init__목록에서 개인용 메소드 제외 (예 :)

사용 중일 수 있습니다. 간단히 말해서, 같은 수업에

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를 준수 하도록 코드 자체 를 리팩터링해야한다는 것을 깨달았지만 앞으로도 무작위로 이질적인 영혼을 제공 할 수 있습니다.


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()완전하고 안정적인 결과 제공

왜 투표가 잘못 되었나요? 그리고 내가 틀린 곳? 그리고 다른 사람들이 대답하는 투표 수가 너무 낮은 곳은 어디입니까?


1
methods = [(func, getattr(o, func)) for func in dir(o) if callable(getattr(o, func))]

와 동일한 목록을 제공합니다

methods = inspect.getmembers(o, predicate=inspect.ismethod)

그렇습니다.


0

귀하의 방법이 "정규적인"방법이고 statimethod, classmethod
이 아닌 경우 내가 생각해 낸 약간의 해킹이 있습니다 .

for k, v in your_class.__dict__.items():
    if "function" in str(v):
        print(k)

if조건 에 따라 "기능"을 변경하여 다른 유형의 방법으로 확장 할 수 있습니다 .
파이썬 2.7에서 테스트되었습니다.


1
왜 이것이 다운 투표되었는지 확실하지 않습니다 ... 실제로 내가 가진 문제를 해결했습니다.
redspidermkv

0

다음 코드를 사용하여 파이썬 클래스의 모든 메소드를 나열 할 수 있습니다

dir(className)

클래스의 모든 메소드 이름 목록을 리턴합니다.


-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))

이 코드는 게시 된대로 작동하지 않습니다. class_only 또는 instance_only를 제공하면 목록이 비어있게됩니다.
Oz123

-2

이것은 단지 관찰입니다. "인코딩"은 문자열 객체의 메소드 인 것 같습니다

str_1 = 'a'
str_1.encode('utf-8')
>>> b'a'

그러나 str1이 메소드를 검사하면 빈 목록이 리턴됩니다.

inspect.getmember(str_1, predicate=inspect.ismethod)
>>> []

아마도 내가 틀렸을 수도 있지만 문제는 간단하지 않은 것 같습니다.


1
'a'유형이 인 객체입니다 str. 당신은 이것을 실행하여 이것을 볼 수 있습니다 type('a'). inspect.getmember()유형 매개 변수를 사용하므로 inspect.getmember(str)원하는 것을 보려면 호출해야합니다 .
lhasson

-3
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>)]

-4

파이썬 클래스의 메소드 만 나열하려면

import numpy as np
print(np.random.__all__)

1
그것은 클래스가 아닌 모듈입니다.
Aran-Fey

아란 - 페이 @ 그것은 모든 클래스에 적용되어, 모두가 모든 클래스에 존재입니다
케쉬 차우

2
아닙니다. 모든 모듈에 존재하는 것은 아닙니다 .
Aran-Fey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.