Python sınıfındaki yöntemlerin listesini nasıl alabilirim?


331

1
Kaynak ..... kaynak ...
RickyA

4
@JonCrowell Güç bu şekilde çalışmaz.
Ken Williams

Derleyici direktifini kullanan Cython için binding: stackoverflow.com/a/46041480/1959808
Ioannis Filippidis

4
Python3'te: [f for f in dir(ClassName) if not f.startswith('_')]ya da sadece dir(ClassName)her şey için
Seraf

@Seraf Lütfen yorumlarda cevap göndermeyin. Bunun yerine bir yanıt gönderin.
wjandrea

Yanıtlar:


332

Bir örnek ( optparse.OptionParsersınıfın yöntemlerini listeler ):

>>> 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 tuples listesini döndüren dikkat edin . İlk öğe üyenin adı, ikinci öğe ise değerdir.

Ayrıca aşağıdakilere bir örnek iletebilirsiniz getmembers:

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

4
mükemmel, yüklem parçası anahtar, aksi takdirde ekstra meta bilgi ile dikte ile aynı şeyi alırsınız . Teşekkürler.
Purrell

2
Bu, sınıftaki tüm yöntemlerin bir listesini (diğer sınıflardan devralınan olanlar da dahil olmak üzere) üretecek mi, yoksa yalnızca o sınıfta açıkça tanımlanan yöntemleri listeleyecek mi?
Anderson Green

10
inspect.isroutinedaha uygun bir yüklem olabilir; inspect.ismethodtüm nesnelerin yöntemleri için çalışmaz.
Gavin S. Yancey

1
Bu sadece sınıfın bir örneğini kullanırken işe yaradı (örnekte olduğu gibi). Bu beklenen davranış mı?
Christian Reall-Fluharty

2
python 3.7 üzerinde en azından bu işe yaramaz, sınıfı başlatmak zorunda
kederrac

222

Orada dir(theobject)listedeki tüm alanları ve (bir tuplea gibi) nesnenin yöntemleri yöntemi ve ( " "" olarak), dokümanına sahip alanlar ve yöntemler listelemek için (codeape yazma gibi) modülünü inceleyin.

Her şey (çift alanlar) Python'da çağırılabileceğinden, yalnızca yöntemleri listelemek için yerleşik bir işlev olduğundan emin değilim. Eğer denemek isteyebilirsiniz nesne aracılığıyla almak dirolduğunu çağrılabilir ya da değil.


3
dir (object) kullandığım en basit çözüm.
lstodd

@skjerns Yazmak 5 sembol gerektirir. :)
Dr_Zaszuś

117

Harici kütüphaneler olmadan Python 3.x yanıtı

method_list = [func for func in dir(Foo) if callable(getattr(Foo, func))]

dunder hariç tutulan sonuç:

method_list = [func for func in dir(Foo) if callable(getattr(Foo, func)) and not func.startswith("__")]

38

Liste sınıfıyla ilişkili tüm yöntemleri bilmek istediğinizi varsayalım.

 print (dir(list))

Yukarıdaki liste sınıfının tüm yöntemlerini verecektir


2
Bu en iyi çözüm
Zeeshan Ahmad

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

32

Mülkü deneyin __dict__.


16
Demek istediniz dicti . Ancak bu, yöntemleri değil, örneğin özniteliklerini listeler.
me_and

1
… Bu benim için de işe yaramadı. Markdown sözdizimine başvurduktan sonra __dict__ demek istiyorum.
me_and

3
@me_ve muhtemelen "self .__ dict__" yapıyorsunuz veya daha genel olarak, örnek sürümünü çağırıyorsunuz __dict__. Ancak sınıflar da var __dict__ve bu sınıf yöntemlerini göstermeli :)
Seaux

21

Ayrıca, FunctionType'ı türlerden içe aktarabilir ve aşağıdakilerle test edebilirsiniz 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']

Bu benim için iyi çalıştı. Ben eklentiyi yaptım and not x.startswith('_')görmezden benim kullanım için liste anlama sonuna __init__'s ve özel yöntemler.
Christopher Pearson

2
Sen kurtulabilirsiniz importait FunctionTypeolan bir ıskarta lambda kullanarak type():type(lambda:0)
Tersosauros

isinstanceburadakinden daha iyi olurdu type(y) == FunctionType.
Gloweye

13

Sonuca devralınan (ancak geçersiz kılınmayan) temel sınıflardan yöntemlerin dahil edilmesini isteyip istemediğinizi dikkate almanız gerektiğini unutmayın. dir()Ve inspect.getmembers()operasyon üssü sınıf yöntemlerini içerir, ancak kullanımı __dict__özelliğinde değildir.


3

Bu da işe yarar:

mymodule.py

def foo(x)
   return 'foo'
def bar()
   return 'bar'

Başka bir dosyada

import inspect
import mymodule
method_list = [ func[0] for func in inspect.getmembers(mymodule, predicate=inspect.isroutine) if callable(getattr(mymodule, func[0])) ]

çıktı:

['foo', 'bar']

Python dokümanlarından:

inspect.isroutine (nesne)

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

Yani

print find_defining_class(car, 'speedometer') 

Think Python sayfa 210


3
Girinti 5? Anahtar kelimeler büyük harfle mi yazılıyor? Pep8 tarzı olmayan aralık?
Florrie

1
Naziler kodlama konvansiyonuna bir kez ulaşmadı!
rbennell

1
Bu soruya nasıl cevap veriyor?
Aran-Fey

2

Bu yaklaşım var:

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

Bir sınıf örneği ile uğraşırken , sadece adlar yerine yöntem başvurularıyla bir liste döndürmek daha iyi olur¹. Hedefiniz bu kadar

  1. Hayır kullanarak import
  2. Özel yöntemleri (ör. __init__) Listeden hariç tutma

Yararlı olabilir. Özetle, benzer bir sınıf için

class Ghost:
    def boo(self, who):
        return f'Who you gonna call? {who}'

İle örnek alımını kontrol edebiliriz

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

Böylece hemen arayabilirsiniz:

>>> for method in methods:
...     print(method('GHOSTBUSTERS'))
...
Who you gonna call? GHOSTBUSTERS

Use Kullanım durumu:

Bunu birim testi için kullandım . Tüm yöntemlerin aynı sürecin varyasyonlarını gerçekleştirdiği bir sınıf vardı - bu da uzun testlere yol açtı, her biri diğerlerinden sadece bir tweak uzakta. DRY çok uzak bir rüyaydı.

Tüm yöntemler için tek bir test yapmam gerektiğini düşündüm, bu yüzden yukarıdaki yinelemeyi yaptım.

Her ne kadar ben kodu yine de KURU uyumlu olması için yeniden refactor gerektiğini fark ettim ... Bu yine de gelecekte rastgele bir nitpicky ruh hizmet edebilir.


2

Bunu sadece orada saklıyorum, çünkü en yüksek puanlar net değil .

Bu, Enum'a dayanan normal sınıf olmayan basit bir testtir.

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

Ve bu çıktı sonuçlarıdır.

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

Peki elimizde:

  • dir tam veri sağlama
  • inspect.getmembers tam veri sağlama ve erişilemeyen dahili anahtarlar sağlama getattr()
  • __dict__.keys()sağlamak eksiksiz ve güvenilir bir sonuç

Oylar neden bu kadar hatalı? Ve nerede yanılıyorum? Ve cevapları veren diğer insanların bu kadar düşük oyları nerede?


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

ile aynı listeyi verir

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

yapar.


0

Eğer metodunuz bir "normal" metoduysa, a değil statimethod, classmethodvb.

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

Bu, ilgili koşuldaki "işlev" değiştirilerek diğer yöntem türlerine genişletilebilir if.
Python 2.7 üzerinde test edilmiştir.


1
Bunun neden reddedildiğinden emin değilim ... yaşadığım problemi gerçekten çözdü.
redspidermkv

0

Aşağıdaki kodu kullanarak bir python sınıfındaki tüm yöntemleri listeleyebilirsiniz

dir(className)

Bu, sınıftaki yöntemlerin tüm adlarının bir listesini döndürür


-1

Bu eski bir yazı olduğunu biliyorum, ama sadece bu işlevi yazdı ve burada bırakacak biri cevap arayan tökezler durumda:

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

Bu kod, yayınlandığı gibi yapmaz. Class_only veya instance_only vermek boş listeyle sonuçlanır.
Oz123

-2

Bu sadece bir gözlem. "encode" dize nesneleri için bir yöntem gibi görünüyor

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

Ancak, str1 yöntemler için denetlenirse, boş bir liste döndürülür

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

Yani, belki yanılıyorum, ama sorun basit görünmüyor.


1
'a'türü olan bir nesnedir str. Bunu koşarak görebilirsiniz type('a'). inspect.getmember()bir type parametresi alır, bu nedenle inspect.getmember(str)ne beklediğinizi görmek için aramanız gerekir .
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('__')])

çıktı

[('run', <function CPerson.run at 0x0000000002AD3268>)]
[('age', <property object at 0x0000000002368688>), ('my_static_method', <staticmethod object at 0x0000000002ACBD68>), ('say', <classmethod object at 0x0000000002ACF0B8>)]

-4

Yalnızca bir python sınıfının yöntemlerini listelemek istiyorsanız

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

1
Bu bir modül, sınıf değil.
Aran-Fey

@ Aran-Fey Her sınıf için uygulanır, her sınıfta her şey vardır
Rakesh Chaudhari

2
Hayır. Tüm modüllerde bile mevcut değildir .
Aran-Fey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.