标签归档:inspect

如何读取包含默认参数值的函数签名?

问题:如何读取包含默认参数值的函数签名?

给定一个功能对象,如何获得其签名?例如,用于:

def myMethod(firt, second, third='something'):
    pass

我想得到"myMethod(firt, second, third='something')"

Given a function object, how can I get its signature? For example, for:

def myMethod(firt, second, third='something'):
    pass

I would like to get "myMethod(firt, second, third='something')".


回答 0

import inspect

def foo(a, b, x='blah'):
    pass

print(inspect.getargspec(foo))
# ArgSpec(args=['a', 'b', 'x'], varargs=None, keywords=None, defaults=('blah',))

但是,请注意,inspect.getargspec()自Python 3.0开始不推荐使用。

Python 3.0–3.4建议inspect.getfullargspec()

Python 3.5+建议inspect.signature()

import inspect

def foo(a, b, x='blah'):
    pass

print(inspect.getargspec(foo))
# ArgSpec(args=['a', 'b', 'x'], varargs=None, keywords=None, defaults=('blah',))

However, note that inspect.getargspec() is deprecated since Python 3.0.

Python 3.0–3.4 recommends inspect.getfullargspec().

Python 3.5+ recommends inspect.signature().


回答 1

可以说,找到函数签名的最简单方法是help(function)

>>> def function(arg1, arg2="foo", *args, **kwargs): pass
>>> help(function)
Help on function function in module __main__:

function(arg1, arg2='foo', *args, **kwargs)

另外,在Python 3中,将一个方法添加到inspect名为的模块中signature,该方法旨在表示可调用对象签名及其返回注释

>>> from inspect import signature
>>> def foo(a, *, b:int, **kwargs):
...     pass

>>> sig = signature(foo)

>>> str(sig)
'(a, *, b:int, **kwargs)'

>>> str(sig.parameters['b'])
'b:int'

>>> sig.parameters['b'].annotation
<class 'int'>

Arguably the easiest way to find the signature for a function would be help(function):

>>> def function(arg1, arg2="foo", *args, **kwargs): pass
>>> help(function)
Help on function function in module __main__:

function(arg1, arg2='foo', *args, **kwargs)

Also, in Python 3 a method was added to the inspect module called signature, which is designed to represent the signature of a callable object and its return annotation:

>>> from inspect import signature
>>> def foo(a, *, b:int, **kwargs):
...     pass

>>> sig = signature(foo)

>>> str(sig)
'(a, *, b:int, **kwargs)'

>>> str(sig.parameters['b'])
'b:int'

>>> sig.parameters['b'].annotation
<class 'int'>

回答 2

#! /usr/bin/env python

import inspect
from collections import namedtuple

DefaultArgSpec = namedtuple('DefaultArgSpec', 'has_default default_value')

def _get_default_arg(args, defaults, arg_index):
    """ Method that determines if an argument has default value or not,
    and if yes what is the default value for the argument

    :param args: array of arguments, eg: ['first_arg', 'second_arg', 'third_arg']
    :param defaults: array of default values, eg: (42, 'something')
    :param arg_index: index of the argument in the argument array for which,
    this function checks if a default value exists or not. And if default value
    exists it would return the default value. Example argument: 1
    :return: Tuple of whether there is a default or not, and if yes the default
    value, eg: for index 2 i.e. for "second_arg" this function returns (True, 42)
    """
    if not defaults:
        return DefaultArgSpec(False, None)

    args_with_no_defaults = len(args) - len(defaults)

    if arg_index < args_with_no_defaults:
        return DefaultArgSpec(False, None)
    else:
        value = defaults[arg_index - args_with_no_defaults]
        if (type(value) is str):
            value = '"%s"' % value
        return DefaultArgSpec(True, value)

def get_method_sig(method):
    """ Given a function, it returns a string that pretty much looks how the
    function signature would be written in python.

    :param method: a python method
    :return: A string similar describing the pythong method signature.
    eg: "my_method(first_argArg, second_arg=42, third_arg='something')"
    """

    # The return value of ArgSpec is a bit weird, as the list of arguments and
    # list of defaults are returned in separate array.
    # eg: ArgSpec(args=['first_arg', 'second_arg', 'third_arg'],
    # varargs=None, keywords=None, defaults=(42, 'something'))
    argspec = inspect.getargspec(method)
    arg_index=0
    args = []

    # Use the args and defaults array returned by argspec and find out
    # which arguments has default
    for arg in argspec.args:
        default_arg = _get_default_arg(argspec.args, argspec.defaults, arg_index)
        if default_arg.has_default:
            args.append("%s=%s" % (arg, default_arg.default_value))
        else:
            args.append(arg)
        arg_index += 1
    return "%s(%s)" % (method.__name__, ", ".join(args))


if __name__ == '__main__':
    def my_method(first_arg, second_arg=42, third_arg='something'):
        pass

    print get_method_sig(my_method)
    # my_method(first_argArg, second_arg=42, third_arg="something")
#! /usr/bin/env python

import inspect
from collections import namedtuple

DefaultArgSpec = namedtuple('DefaultArgSpec', 'has_default default_value')

def _get_default_arg(args, defaults, arg_index):
    """ Method that determines if an argument has default value or not,
    and if yes what is the default value for the argument

    :param args: array of arguments, eg: ['first_arg', 'second_arg', 'third_arg']
    :param defaults: array of default values, eg: (42, 'something')
    :param arg_index: index of the argument in the argument array for which,
    this function checks if a default value exists or not. And if default value
    exists it would return the default value. Example argument: 1
    :return: Tuple of whether there is a default or not, and if yes the default
    value, eg: for index 2 i.e. for "second_arg" this function returns (True, 42)
    """
    if not defaults:
        return DefaultArgSpec(False, None)

    args_with_no_defaults = len(args) - len(defaults)

    if arg_index < args_with_no_defaults:
        return DefaultArgSpec(False, None)
    else:
        value = defaults[arg_index - args_with_no_defaults]
        if (type(value) is str):
            value = '"%s"' % value
        return DefaultArgSpec(True, value)

def get_method_sig(method):
    """ Given a function, it returns a string that pretty much looks how the
    function signature would be written in python.

    :param method: a python method
    :return: A string similar describing the pythong method signature.
    eg: "my_method(first_argArg, second_arg=42, third_arg='something')"
    """

    # The return value of ArgSpec is a bit weird, as the list of arguments and
    # list of defaults are returned in separate array.
    # eg: ArgSpec(args=['first_arg', 'second_arg', 'third_arg'],
    # varargs=None, keywords=None, defaults=(42, 'something'))
    argspec = inspect.getargspec(method)
    arg_index=0
    args = []

    # Use the args and defaults array returned by argspec and find out
    # which arguments has default
    for arg in argspec.args:
        default_arg = _get_default_arg(argspec.args, argspec.defaults, arg_index)
        if default_arg.has_default:
            args.append("%s=%s" % (arg, default_arg.default_value))
        else:
            args.append(arg)
        arg_index += 1
    return "%s(%s)" % (method.__name__, ", ".join(args))


if __name__ == '__main__':
    def my_method(first_arg, second_arg=42, third_arg='something'):
        pass

    print get_method_sig(my_method)
    # my_method(first_argArg, second_arg=42, third_arg="something")

回答 3

尝试调用help一个对象以了解它。

>>> foo = [1, 2, 3]
>>> help(foo.append)
Help on built-in function append:

append(...)
    L.append(object) -- append object to end

Try calling help on an object to find out about it.

>>> foo = [1, 2, 3]
>>> help(foo.append)
Help on built-in function append:

append(...)
    L.append(object) -- append object to end

回答 4

可能要晚一些,但是如果您还想保留参数的顺序及其默认值,则可以使用抽象语法树模块(ast)

这是一个概念证明(请注意,对参数进行排序并将其与默认值匹配的代码肯定可以得到改善/更加清晰):

import ast

for class_ in [c for c in module.body if isinstance(c, ast.ClassDef)]:
    for method in [m for m in class_.body if isinstance(m, ast.FunctionDef)]:
        args = []
        if method.args.args:
            [args.append([a.col_offset, a.id]) for a in method.args.args]
        if method.args.defaults:
            [args.append([a.col_offset, '=' + a.id]) for a in method.args.defaults]
        sorted_args = sorted(args)
        for i, p in enumerate(sorted_args):
            if p[1].startswith('='):
                sorted_args[i-1][1] += p[1]
        sorted_args = [k[1] for k in sorted_args if not k[1].startswith('=')]

        if method.args.vararg:
            sorted_args.append('*' + method.args.vararg)
        if method.args.kwarg:
            sorted_args.append('**' + method.args.kwarg)

        signature = '(' + ', '.join(sorted_args) + ')'

        print method.name + signature

Maybe a bit late to the party, but if you also want to keep the order of the arguments and their defaults, then you can use the Abstract Syntax Tree module (ast).

Here’s a proof of concept (beware the code to sort the arguments and match them to their defaults can definitely be improved/made more clear):

import ast

for class_ in [c for c in module.body if isinstance(c, ast.ClassDef)]:
    for method in [m for m in class_.body if isinstance(m, ast.FunctionDef)]:
        args = []
        if method.args.args:
            [args.append([a.col_offset, a.id]) for a in method.args.args]
        if method.args.defaults:
            [args.append([a.col_offset, '=' + a.id]) for a in method.args.defaults]
        sorted_args = sorted(args)
        for i, p in enumerate(sorted_args):
            if p[1].startswith('='):
                sorted_args[i-1][1] += p[1]
        sorted_args = [k[1] for k in sorted_args if not k[1].startswith('=')]

        if method.args.vararg:
            sorted_args.append('*' + method.args.vararg)
        if method.args.kwarg:
            sorted_args.append('**' + method.args.kwarg)

        signature = '(' + ', '.join(sorted_args) + ')'

        print method.name + signature

回答 5

如果您只想打印功能,请使用pydoc。

import pydoc    

def foo(arg1, arg2, *args, **kwargs):                                                                    
    '''Some foo fn'''                                                                                    
    pass                                                                                                 

>>> print pydoc.render_doc(foo).splitlines()[2]
foo(arg1, arg2, *args, **kwargs)

如果您尝试实际分析功能签名,请使用检查模块的argspec。在将用户的挂钩脚本功能验证到通用框架中时,我必须这样做。

If all you’re trying to do is print the function then use pydoc.

import pydoc    

def foo(arg1, arg2, *args, **kwargs):                                                                    
    '''Some foo fn'''                                                                                    
    pass                                                                                                 

>>> print pydoc.render_doc(foo).splitlines()[2]
foo(arg1, arg2, *args, **kwargs)

If you’re trying to actually analyze the function signature then use argspec of the inspection module. I had to do that when validating a user’s hook script function into a general framework.


回答 6

示例代码:

import inspect
from collections import OrderedDict


def get_signature(fn):
    params = inspect.signature(fn).parameters
    args = []
    kwargs = OrderedDict()
    for p in params.values():
        if p.default is p.empty:
            args.append(p.name)
        else:
            kwargs[p.name] = p.default
    return args, kwargs


def test_sig():
    def fn(a, b, c, d=3, e="abc"):
        pass

    assert get_signature(fn) == (
        ["a", "b", "c"], OrderedDict([("d", 3), ("e", "abc")])
    )

Example code:

import inspect
from collections import OrderedDict


def get_signature(fn):
    params = inspect.signature(fn).parameters
    args = []
    kwargs = OrderedDict()
    for p in params.values():
        if p.default is p.empty:
            args.append(p.name)
        else:
            kwargs[p.name] = p.default
    return args, kwargs


def test_sig():
    def fn(a, b, c, d=3, e="abc"):
        pass

    assert get_signature(fn) == (
        ["a", "b", "c"], OrderedDict([("d", 3), ("e", "abc")])
    )

回答 7

在命令行(IPython)中使用%pdef,它将仅打印签名。

例如 %pdef np.loadtxt

 np.loadtxt(fname, dtype=<class 'float'>, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding='bytes')

Use %pdef in the command line (IPython), it will print only the signature.

e.g. %pdef np.loadtxt

 np.loadtxt(fname, dtype=<class 'float'>, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding='bytes')

如何获取Python当前模块中所有类的列表?

问题:如何获取Python当前模块中所有类的列表?

我见过很多人从一个模块中提取所有类的示例,通常是这样的:

# foo.py
class Foo:
    pass

# test.py
import inspect
import foo

for name, obj in inspect.getmembers(foo):
    if inspect.isclass(obj):
        print obj

太棒了

但是我无法找到如何从当前模块中获取所有类。

# foo.py
import inspect

class Foo:
    pass

def print_classes():
    for name, obj in inspect.getmembers(???): # what do I do here?
        if inspect.isclass(obj):
            print obj

# test.py
import foo

foo.print_classes()

这可能确实很明显,但是我什么也找不到。谁能帮我吗?

I’ve seen plenty of examples of people extracting all of the classes from a module, usually something like:

# foo.py
class Foo:
    pass

# test.py
import inspect
import foo

for name, obj in inspect.getmembers(foo):
    if inspect.isclass(obj):
        print obj

Awesome.

But I can’t find out how to get all of the classes from the current module.

# foo.py
import inspect

class Foo:
    pass

def print_classes():
    for name, obj in inspect.getmembers(???): # what do I do here?
        if inspect.isclass(obj):
            print obj

# test.py
import foo

foo.print_classes()

This is probably something really obvious, but I haven’t been able to find anything. Can anyone help me out?


回答 0

尝试这个:

import sys
current_module = sys.modules[__name__]

在您的情况下:

import sys, inspect
def print_classes():
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj):
            print(obj)

甚至更好:

clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass)

因为inspect.getmembers()带谓语。

Try this:

import sys
current_module = sys.modules[__name__]

In your context:

import sys, inspect
def print_classes():
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj):
            print(obj)

And even better:

clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass)

Because inspect.getmembers() takes a predicate.


回答 1

关于什么

g = globals().copy()
for name, obj in g.iteritems():

What about

g = globals().copy()
for name, obj in g.iteritems():

?


回答 2

我不知道是否有“适当的”方法来执行此操作,但是您的代码片段import foo处在正确的轨道上:只需将其添加到foo.py中,do inspect.getmembers(foo),它就可以正常工作。

I don’t know if there’s a ‘proper’ way to do it, but your snippet is on the right track: just add import foo to foo.py, do inspect.getmembers(foo), and it should work fine.


回答 3

我能够从dir内置plus中获得所需的一切getattr

# Works on pretty much everything, but be mindful that 
# you get lists of strings back

print dir(myproject)
print dir(myproject.mymodule)
print dir(myproject.mymodule.myfile)
print dir(myproject.mymodule.myfile.myclass)

# But, the string names can be resolved with getattr, (as seen below)

虽然,它的确看起来像个毛线球:

def list_supported_platforms():
    """
        List supported platforms (to match sys.platform)

        @Retirms:
            list str: platform names
    """
    return list(itertools.chain(
        *list(
            # Get the class's constant
            getattr(
                # Get the module's first class, which we wrote
                getattr(
                    # Get the module
                    getattr(platforms, item),
                    dir(
                        getattr(platforms, item)
                    )[0]
                ),
                'SYS_PLATFORMS'
            )
            # For each include in platforms/__init__.py 
            for item in dir(platforms)
            # Ignore magic, ourselves (index.py) and a base class.
            if not item.startswith('__') and item not in ['index', 'base']
        )
    ))

I was able to get all I needed from the dir built in plus getattr.

# Works on pretty much everything, but be mindful that 
# you get lists of strings back

print dir(myproject)
print dir(myproject.mymodule)
print dir(myproject.mymodule.myfile)
print dir(myproject.mymodule.myfile.myclass)

# But, the string names can be resolved with getattr, (as seen below)

Though, it does come out looking like a hairball:

def list_supported_platforms():
    """
        List supported platforms (to match sys.platform)

        @Retirms:
            list str: platform names
    """
    return list(itertools.chain(
        *list(
            # Get the class's constant
            getattr(
                # Get the module's first class, which we wrote
                getattr(
                    # Get the module
                    getattr(platforms, item),
                    dir(
                        getattr(platforms, item)
                    )[0]
                ),
                'SYS_PLATFORMS'
            )
            # For each include in platforms/__init__.py 
            for item in dir(platforms)
            # Ignore magic, ourselves (index.py) and a base class.
            if not item.startswith('__') and item not in ['index', 'base']
        )
    ))

回答 4

import pyclbr
print(pyclbr.readmodule(__name__).keys())

请注意,stdlib的Python类浏览器模块使用静态源分析,因此它仅适用于由实际.py文件支持的模块。

import pyclbr
print(pyclbr.readmodule(__name__).keys())

Note that the stdlib’s Python class browser module uses static source analysis, so it only works for modules that are backed by a real .py file.


回答 5

如果要拥有属于当前模块的所有类,则可以使用以下方法:

import sys, inspect
def print_classes():
    is_class_member = lambda member: inspect.isclass(member) and member.__module__ == __name__
    clsmembers = inspect.getmembers(sys.modules[__name__], is_class_member)

如果您使用Nadia的答案并且要在模块上导入其他类,则这些类也将被导入。

因此,这就是为什么member.__module__ == __name__要添加到上使用的谓词的原因is_class_member。该语句检查该类是否确实属于该模块。

谓词是一个函数(可调用),它返回布尔值。

If you want to have all the classes, that belong to the current module, you could use this :

import sys, inspect
def print_classes():
    is_class_member = lambda member: inspect.isclass(member) and member.__module__ == __name__
    clsmembers = inspect.getmembers(sys.modules[__name__], is_class_member)

If you use Nadia’s answer and you were importing other classes on your module, that classes will be being imported too.

So that’s why member.__module__ == __name__ is being added to the predicate used on is_class_member. This statement checks that the class really belongs to the module.

A predicate is a function (callable), that returns a boolean value.


回答 6

另一个可在Python 2和3中使用的解决方案:

#foo.py
import sys

class Foo(object):
    pass

def print_classes():
    current_module = sys.modules[__name__]
    for key in dir(current_module):
        if isinstance( getattr(current_module, key), type ):
            print(key)

# test.py
import foo
foo.print_classes()

Another solution which works in Python 2 and 3:

#foo.py
import sys

class Foo(object):
    pass

def print_classes():
    current_module = sys.modules[__name__]
    for key in dir(current_module):
        if isinstance( getattr(current_module, key), type ):
            print(key)

# test.py
import foo
foo.print_classes()

回答 7

这是我用来获取当前模块中已定义(即未导入)的所有类的行。根据PEP-8,它有点长,但是您可以根据需要进行更改。

import sys
import inspect

classes = [name for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass) 
          if obj.__module__ is __name__]

这为您提供了一个类名列表。如果您想要类对象本身,只需保留obj即可。

classes = [obj for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass)
          if obj.__module__ is __name__]

根据我的经验,这是更有用的。

This is the line that I use to get all of the classes that have been defined in the current module (ie not imported). It’s a little long according to PEP-8 but you can change it as you see fit.

import sys
import inspect

classes = [name for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass) 
          if obj.__module__ is __name__]

This gives you a list of the class names. If you want the class objects themselves just keep obj instead.

classes = [obj for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass)
          if obj.__module__ is __name__]

This is has been more useful in my experience.


回答 8

import Foo 
dir(Foo)

import collections
dir(collections)
import Foo 
dir(Foo)

import collections
dir(collections)

回答 9

我认为您可以做这样的事情。

class custom(object):
    __custom__ = True
class Alpha(custom):
    something = 3
def GetClasses():
    return [x for x in globals() if hasattr(globals()[str(x)], '__custom__')]
print(GetClasses())`

如果您需要自己的类

I think that you can do something like this.

class custom(object):
    __custom__ = True
class Alpha(custom):
    something = 3
def GetClasses():
    return [x for x in globals() if hasattr(globals()[str(x)], '__custom__')]
print(GetClasses())`

if you need own classes


回答 10

我经常发现自己在编写命令行实用程序,其中第一个参数旨在引用许多不同类中的一个。例如./something.py feature command —-arguments,where Feature是一个类,并且command是该类上的一个方法。这是一个使这变得容易的基类。

假设该基类与所有子类都位于一个目录中。然后ArgBaseClass(foo = bar).load_subclasses(),您可以拨打电话,这将返回字典。例如,如果目录如下所示:

  • arg_base_class.py
  • feature.py

假设feature.py工具class Feature(ArgBaseClass),则上述调用load_subclasses将返回{ 'feature' : <Feature object> }。相同的kwargsfoo = bar)将传递给Feature该类。

#!/usr/bin/env python3
import os, pkgutil, importlib, inspect

class ArgBaseClass():
    # Assign all keyword arguments as properties on self, and keep the kwargs for later.
    def __init__(self, **kwargs):
        self._kwargs = kwargs
        for (k, v) in kwargs.items():
            setattr(self, k, v)
        ms = inspect.getmembers(self, predicate=inspect.ismethod)
        self.methods = dict([(n, m) for (n, m) in ms if not n.startswith('_')])

    # Add the names of the methods to a parser object.
    def _parse_arguments(self, parser):
        parser.add_argument('method', choices=list(self.methods))
        return parser

    # Instantiate one of each of the subclasses of this class.
    def load_subclasses(self):
        module_dir = os.path.dirname(__file__)
        module_name = os.path.basename(os.path.normpath(module_dir))
        parent_class = self.__class__
        modules = {}
        # Load all the modules it the package:
        for (module_loader, name, ispkg) in pkgutil.iter_modules([module_dir]):
            modules[name] = importlib.import_module('.' + name, module_name)

        # Instantiate one of each class, passing the keyword arguments.
        ret = {}
        for cls in parent_class.__subclasses__():
            path = cls.__module__.split('.')
            ret[path[-1]] = cls(**self._kwargs)
        return ret

I frequently find myself writing command line utilities wherein the first argument is meant to refer to one of many different classes. For example ./something.py feature command —-arguments, where Feature is a class and command is a method on that class. Here’s a base class that makes this easy.

The assumption is that this base class resides in a directory alongside all of its subclasses. You can then call ArgBaseClass(foo = bar).load_subclasses() which will return a dictionary. For example, if the directory looks like this:

  • arg_base_class.py
  • feature.py

Assuming feature.py implements class Feature(ArgBaseClass), then the above invocation of load_subclasses will return { 'feature' : <Feature object> }. The same kwargs (foo = bar) will be passed into the Feature class.

#!/usr/bin/env python3
import os, pkgutil, importlib, inspect

class ArgBaseClass():
    # Assign all keyword arguments as properties on self, and keep the kwargs for later.
    def __init__(self, **kwargs):
        self._kwargs = kwargs
        for (k, v) in kwargs.items():
            setattr(self, k, v)
        ms = inspect.getmembers(self, predicate=inspect.ismethod)
        self.methods = dict([(n, m) for (n, m) in ms if not n.startswith('_')])

    # Add the names of the methods to a parser object.
    def _parse_arguments(self, parser):
        parser.add_argument('method', choices=list(self.methods))
        return parser

    # Instantiate one of each of the subclasses of this class.
    def load_subclasses(self):
        module_dir = os.path.dirname(__file__)
        module_name = os.path.basename(os.path.normpath(module_dir))
        parent_class = self.__class__
        modules = {}
        # Load all the modules it the package:
        for (module_loader, name, ispkg) in pkgutil.iter_modules([module_dir]):
            modules[name] = importlib.import_module('.' + name, module_name)

        # Instantiate one of each class, passing the keyword arguments.
        ret = {}
        for cls in parent_class.__subclasses__():
            path = cls.__module__.split('.')
            ret[path[-1]] = cls(**self._kwargs)
        return ret

如何列出Python模块中的所有功能?

问题:如何列出Python模块中的所有功能?

我的系统上安装了python模块,我希望能够看到其中可用的函数/类/方法。

我想在每个函数上调用doc函数。在ruby中,我可以执行ClassName.methods之类的操作来获取该类上所有可用方法的列表。python中是否有类似的东西?

例如。就像是:

from somemodule import foo
print foo.methods # or whatever is the correct method to call

I have a python module installed on my system and I’d like to be able to see what functions/classes/methods are available in it.

I want to call the doc function on each one. In ruby I can do something like ClassName.methods to get a list of all the methods available on that class. Is there something similar in python?

eg. something like:

from somemodule import foo
print foo.methods # or whatever is the correct method to call

回答 0

inspect模块。另请参阅pydoc模块,help()交互式解释器中的功能以及pydoc生成所需文档的命令行工具。您可以给他们想要查看其文档的类。他们还可以生成例如HTML输出并将其写入磁盘。

The inspect module. Also see the pydoc module, the help() function in the interactive interpreter and the pydoc command-line tool which generates the documentation you are after. You can just give them the class you wish to see the documentation of. They can also generate, for instance, HTML output and write it to disk.


回答 1

您可以dir(module)用来查看所有可用的方法/属性。还要检查PyDocs。

You can use dir(module) to see all available methods/attributes. Also check out PyDocs.


回答 2

一旦你import编的模块,你可以做:

 help(modulename)

…要一次以交互方式获取所有功能的文档。或者您可以使用:

 dir(modulename)

…简单列出模块中定义的所有函数和变量的名称。

Once you’ve imported the module, you can just do:

 help(modulename)

… To get the docs on all the functions at once, interactively. Or you can use:

 dir(modulename)

… To simply list the names of all the functions and variables defined in the module.


回答 3

带inspect的例子:

from inspect import getmembers, isfunction
from my_project import my_module

functions_list = [o for o in getmembers(my_module) if isfunction(o[1])]

getmembers返回(object_name,object_type)元组的列表。

您可以在检查模块中将isfunction替换为任何其他isXXX函数。

An example with inspect:

from inspect import getmembers, isfunction
from my_project import my_module

functions_list = [o for o in getmembers(my_module) if isfunction(o[1])]

getmembers returns a list of (object_name, object_type) tuples.

You can replace isfunction with any of the other isXXX functions in the inspect module.


回答 4

import types
import yourmodule

print([getattr(yourmodule, a) for a in dir(yourmodule)
  if isinstance(getattr(yourmodule, a), types.FunctionType)])
import types
import yourmodule

print([getattr(yourmodule, a) for a in dir(yourmodule)
  if isinstance(getattr(yourmodule, a), types.FunctionType)])

回答 5

为了完整起见,我想指出,有时您可能想解析代码而不是导入代码。一个import执行最高水平的表达,这可能是一个问题。

例如,我让用户为zipapp制作的软件包选择入口点功能。使用误入歧途的代码importinspect冒着导致误入歧途的风险,从而导致崩溃,打印帮助信息,弹出GUI对话框等。

相反,我使用ast模块列出所有顶级功能:

import ast
import sys

def top_level_functions(body):
    return (f for f in body if isinstance(f, ast.FunctionDef))

def parse_ast(filename):
    with open(filename, "rt") as file:
        return ast.parse(file.read(), filename=filename)

if __name__ == "__main__":
    for filename in sys.argv[1:]:
        print(filename)
        tree = parse_ast(filename)
        for func in top_level_functions(tree.body):
            print("  %s" % func.name)

将这段代码放入list.py并用作输入,我得到:

$ python list.py list.py
list.py
  top_level_functions
  parse_ast

当然,即使对于像Python这样的相对简单的语言,导航AST有时也会很棘手,因为AST的层次很低。但是,如果您有一个简单明了的用例,那么它既可行又安全。

不过,缺点是您无法检测到运行时生成的函数,例如foo = lambda x,y: x*y

For completeness’ sake, I’d like to point out that sometimes you may want to parse code instead of importing it. An import will execute top-level expressions, and that could be a problem.

For example, I’m letting users select entry point functions for packages being made with zipapp. Using import and inspect risks running astray code, leading to crashes, help messages being printed out, GUI dialogs popping up and so on.

Instead I use the ast module to list all the top-level functions:

import ast
import sys

def top_level_functions(body):
    return (f for f in body if isinstance(f, ast.FunctionDef))

def parse_ast(filename):
    with open(filename, "rt") as file:
        return ast.parse(file.read(), filename=filename)

if __name__ == "__main__":
    for filename in sys.argv[1:]:
        print(filename)
        tree = parse_ast(filename)
        for func in top_level_functions(tree.body):
            print("  %s" % func.name)

Putting this code in list.py and using itself as input, I get:

$ python list.py list.py
list.py
  top_level_functions
  parse_ast

Of course, navigating an AST can be tricky sometimes, even for a relatively simple language like Python, because the AST is quite low-level. But if you have a simple and clear use case, it’s both doable and safe.

Though, a downside is that you can’t detect functions that are generated at runtime, like foo = lambda x,y: x*y.


回答 6

对于您不希望解析的代码,我建议上面使用基于AST的@csl方法。

对于其他所有内容,inspect模块都是正确的:

import inspect

import <module_to_inspect> as module

functions = inspect.getmembers(module, inspect.isfunction)

这给出了形式为2元组的列表[(<name:str>, <value:function>), ...]

上面的简单答案在各种回复和评论中都有提示,但没有明确指出。

For code that you do not wish to parse, I recommend the AST-based approach of @csl above.

For everything else, the inspect module is correct:

import inspect

import <module_to_inspect> as module

functions = inspect.getmembers(module, inspect.isfunction)

This gives a list of 2-tuples in the form [(<name:str>, <value:function>), ...].

The simple answer above is hinted at in various responses and comments, but not called out explicitly.


回答 7

这将达到目的:

dir(module) 

但是,如果您发现读取返回的列表很烦人,则只需使用以下循环即可获得每行一个名称。

for i in dir(module): print i

This will do the trick:

dir(module) 

However, if you find it annoying to read the returned list, just use the following loop to get one name per line.

for i in dir(module): print i

回答 8

dir(module) 如大多数答案中所述,这是使用脚本或标准解释器时的标准方法。

但是,使用像IPython这样的交互式python shell,您可以使用tab-completion来概述模块中定义的所有对象。这比使用脚本并print查看模块中定义的内容要方便得多。

  • module.<tab> 将向您显示模块中定义的所有对象(函数,类等)
  • module.ClassX.<tab> 将向您展示类的方法和属性
  • module.function_xy?module.ClassX.method_xy?将向您显示该函数/方法的文档字符串
  • module.function_x??module.SomeClass.method_xy??将显示函数/方法的源代码。

dir(module) is the standard way when using a script or the standard interpreter, as mentioned in most answers.

However with an interactive python shell like IPython you can use tab-completion to get an overview of all objects defined in the module. This is much more convenient, than using a script and print to see what is defined in the module.

  • module.<tab> will show you all objects defined in the module (functions, classes and so on)
  • module.ClassX.<tab> will show you the methods and attributes of a class
  • module.function_xy? or module.ClassX.method_xy? will show you the docstring of that function / method
  • module.function_x?? or module.SomeClass.method_xy?? will show you the source code of the function / method.

回答 9

对于全局函数,dir()是要使用的命令(如大多数答案中所提到的),但是此命令同时列出了公共函数和非公共函数。

例如运行:

>>> import re
>>> dir(re)

返回类似的函数/类:

'__all__', '_MAXCACHE', '_alphanum_bytes', '_alphanum_str', '_pattern_type', '_pickle', '_subx'

其中一些通常不用于一般编程用途(但由模块本身提供,除非在DunderAliases之类的情况下, __doc____file__ECT)。因此,将它们与公开对象一起列出可能没有用(这是Python知道使用时会得到什么的方式from module import *)。

__all__可用于解决此问题,它会返回模块中所有公共函数和类的列表(这些函数和类以下划线开头-_)。请参见 有人可以用Python解释__all__吗?用于__all__

这是一个例子:

>>> import re
>>> re.__all__
['match', 'fullmatch', 'search', 'sub', 'subn', 'split', 'findall', 'finditer', 'compile', 'purge', 'template', 'escape', 'error', 'A', 'I', 'L', 'M', 'S', 'X', 'U', 'ASCII', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL', 'VERBOSE', 'UNICODE']
>>>

所有带下划线的函数和类均已删除,仅保留那些定义为public的函数和类,因此可以通过来使用import *

请注意,__all__并非总是定义。如果不包括在内,则AttributeError则引发一个。

ast模块就是一个例子:

>>> import ast
>>> ast.__all__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'ast' has no attribute '__all__'
>>>

For global functions dir() is the command to use (as mentioned in most of these answers), however this lists both public functions and non-public functions together.

For example running:

>>> import re
>>> dir(re)

Returns functions/classes like:

'__all__', '_MAXCACHE', '_alphanum_bytes', '_alphanum_str', '_pattern_type', '_pickle', '_subx'

Some of which are not generally meant for general programming use (but by the module itself, except in the case of DunderAliases like __doc__, __file__ ect). For this reason it may not be useful to list them with the public ones (this is how Python knows what to get when using from module import *).

__all__ could be used to solve this problem, it returns a list of all the public functions and classes in a module (those that do not start with underscores – _). See Can someone explain __all__ in Python? for the use of __all__.

Here is an example:

>>> import re
>>> re.__all__
['match', 'fullmatch', 'search', 'sub', 'subn', 'split', 'findall', 'finditer', 'compile', 'purge', 'template', 'escape', 'error', 'A', 'I', 'L', 'M', 'S', 'X', 'U', 'ASCII', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL', 'VERBOSE', 'UNICODE']
>>>

All the functions and classes with underscores have been removed, leaving only those that are defined as public and can therefore be used via import *.

Note that __all__ is not always defined. If it is not included then an AttributeError is raised.

A case of this is with the ast module:

>>> import ast
>>> ast.__all__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'ast' has no attribute '__all__'
>>>

回答 10

如果您无法在没有导入错误的情况下导入所述Python文件,则这些答案均无效。当我检查文件时,我的情况就是这样,该文件来自具有很多依赖关系的大型代码库。下面将以文本形式处理文件,并搜索所有以“ def”开头的方法名称,并打印它们及其行号。

import re
pattern = re.compile("def (.*)\(")
for i, line in enumerate(open('Example.py')):
  for match in re.finditer(pattern, line):
    print '%s: %s' % (i+1, match.groups()[0])

None of these answers will work if you are unable to import said Python file without import errors. This was the case for me when I was inspecting a file which comes from a large code base with a lot of dependencies. The following will process the file as text and search for all method names that start with “def” and print them and their line numbers.

import re
pattern = re.compile("def (.*)\(")
for i, line in enumerate(open('Example.py')):
  for match in re.finditer(pattern, line):
    print '%s: %s' % (i+1, match.groups()[0])

回答 11

除了前面的答案中提到的dir(模块)或help(模块),您还可以尝试:
-打开ipython-
导入module_name-
键入module_name,然后按tab。它将打开一个小窗口,其中列出了python模块中的所有功能。
看起来很整洁。

这是列出hashlib模块所有功能的代码段

(C:\Program Files\Anaconda2) C:\Users\lenovo>ipython
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import hashlib

In [2]: hashlib.
             hashlib.algorithms            hashlib.new                   hashlib.sha256
             hashlib.algorithms_available  hashlib.pbkdf2_hmac           hashlib.sha384
             hashlib.algorithms_guaranteed hashlib.sha1                  hashlib.sha512
             hashlib.md5                   hashlib.sha224

Except dir(module) or help(module) mentioned in previous answers, you can also try:
– Open ipython
– import module_name
– type module_name, press tab. It’ll open a small window with listing all functions in the python module.
It looks very neat.

Here is snippet listing all functions of hashlib module

(C:\Program Files\Anaconda2) C:\Users\lenovo>ipython
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import hashlib

In [2]: hashlib.
             hashlib.algorithms            hashlib.new                   hashlib.sha256
             hashlib.algorithms_available  hashlib.pbkdf2_hmac           hashlib.sha384
             hashlib.algorithms_guaranteed hashlib.sha1                  hashlib.sha512
             hashlib.md5                   hashlib.sha224

回答 12

这将在列表中附加在your_module中定义的所有功能。

result=[]
for i in dir(your_module):
    if type(getattr(your_module, i)).__name__ == "function":
        result.append(getattr(your_module, i))

This will append all the functions that are defined in your_module in a list.

result=[]
for i in dir(your_module):
    if type(getattr(your_module, i)).__name__ == "function":
        result.append(getattr(your_module, i))

回答 13

您可以使用以下方法从shell列出模块中的所有功能:

import module

module.*?

You can use the following method to get list all the functions in your module from shell:

import module

module.*?

回答 14

import sys
from inspect import getmembers, isfunction
fcn_list = [o[0] for o in getmembers(sys.modules[__name__], isfunction)]
import sys
from inspect import getmembers, isfunction
fcn_list = [o[0] for o in getmembers(sys.modules[__name__], isfunction)]

回答 15

r = globals()
sep = '\n'+100*'*'+'\n' # To make it clean to read.
for k in list(r.keys()):
    try:
        if str(type(r[k])).count('function'):
            print(sep+k + ' : \n' + str(r[k].__doc__))
    except Exception as e:
        print(e)

输出:

******************************************************************************************
GetNumberOfWordsInTextFile : 

    Calcule et retourne le nombre de mots d'un fichier texte
    :param path_: le chemin du fichier à analyser
    :return: le nombre de mots du fichier

******************************************************************************************

    write_in : 

        Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode a,
        :param path_: le path du fichier texte
        :param data_: la liste des données à écrire ou un bloc texte directement
        :return: None


 ******************************************************************************************
    write_in_as_w : 

            Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode w,
            :param path_: le path du fichier texte
            :param data_: la liste des données à écrire ou un bloc texte directement
            :return: None
r = globals()
sep = '\n'+100*'*'+'\n' # To make it clean to read.
for k in list(r.keys()):
    try:
        if str(type(r[k])).count('function'):
            print(sep+k + ' : \n' + str(r[k].__doc__))
    except Exception as e:
        print(e)

Output :

******************************************************************************************
GetNumberOfWordsInTextFile : 

    Calcule et retourne le nombre de mots d'un fichier texte
    :param path_: le chemin du fichier à analyser
    :return: le nombre de mots du fichier

******************************************************************************************

    write_in : 

        Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode a,
        :param path_: le path du fichier texte
        :param data_: la liste des données à écrire ou un bloc texte directement
        :return: None


 ******************************************************************************************
    write_in_as_w : 

            Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode w,
            :param path_: le path du fichier texte
            :param data_: la liste des données à écrire ou un bloc texte directement
            :return: None