gpt4 book ai didi

Python自省(introspection): get the argument list of a method_descriptor?

转载 作者:IT老高 更新时间:2023-10-28 20:42:04 26 4
gpt4 key购买 nike

作为我的问题介绍的代码说明:

import re, inspect, datetime

inspect.getargspec (re.findall)
# =>
# ArgSpec(args = ['pattern', 'string', 'flags'], varargs=None,
# keywords=None, defaults = (0,))

type (datetime.datetime.replace)
# => <type 'method_descriptor'>

inspect.getargspec (datetime.datetime.replace)
# => Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "/usr/lib/python2.7/inspect.py", line 816, in getargspec
# raise TypeError('{!r} is not a Python function'.format(func))
# TypeError: <method 'replace' of 'datetime.datetime' objects> is
# not a Python function

看来我找到datetime.datetime.replace 签名的唯一方法而我的代码是在 the doc 中查找: date.replace(year, month, day) .

似乎唯一有效的内省(introspection)部分:

datetime.datetime.replace.__doc__
# => 'Return datetime with new specified fields.'

我检查了 Jupyter 函数 arglist 工具提示的工作原理,它们有完全相同的问题,即没有可用于 datetime.datetime.replace 的 arglist .

以下是问题:

  1. 是否还有可能以某种方式获取参数列表?也许我可以为 datetime 安装 C 源代码并通过 __file__ 连接它们属性?

  2. 是否可以注释<type 'method_descriptor'>与 arglist 信息?在这种情况下,我可以解析链接文档的 markdown 定义并自动注释内置模块函数。

最佳答案

不,您无法获得更多信息;安装 C 源代码不会让您轻松访问相同的源代码。这是因为在 C 代码中定义的大多数 方法实际上并没有公开这些信息。你必须解析出 rather cryptic piece of C code :

if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace",
datetime_kws,
&y, &m, &d, &hh, &mm, &ss, &us,
&tzinfo, &fold))

re.findall() 函数是 pure Python function ,所以是自省(introspection)的。

我说大多数 方法是用 C 定义的,因为从 Python 3.4 及更高版本开始,方法使用新的 Argument Clinic preprocessor将包含一个新的 __text_signature__ 属性,其内部 inspect._signature_fromstr() function可以解析。这意味着即使对于此类 C 定义的方法,您也可以内省(introspection)参数:

>>> import io
>>> import inspect
>>> type(io.BytesIO.read)
<class 'method_descriptor'>
>>> inspect.signature(io.BytesIO.read)
<Signature (self, size=None, /)>

另见 What are __signature__ and __text_signature__ used for in Python 3.4

datetime 模块还没有得到很多 Argument Clinic 的喜爱。我们必须要有耐心,或者如果您真的很关心这个,请提供将模块转换为使用 Argument Clinic 的补丁。

如果您想了解哪些模块 已经支持,请查看 Modules/clinic subdirectory其中包含生成的诊所输出;对于 datetime 模块,目前仅包含 datetime.datetime.now()。那个方法defines a clinic block :

/*[clinic input]
@classmethod
datetime.datetime.now
tz: object = None
Timezone object.
Returns new datetime object representing current time local to tz.
If no tz is specified, uses local timezone.
[clinic start generated code]*/

static PyObject *
datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz)
/*[clinic end generated code: output=b3386e5345e2b47a input=80d09869c5267d00]*/

使方法可自省(introspection):

>>> import datetime
>>> inspect.signature(datetime.datetime.now)
<Signature (tz=None)>

无法将信息直接附加到那些不可自省(introspection)的 C 函数和方法上;它们也不支持属性。

大多数想要支持此类对象的自动完成解决方案都使用单独的数据结构,其中信息是独立维护的(存在数据不同步的所有固有风险)。其中一些可用于您自己的目的:

  • Komodo IDE 代码智能库(开源,也使用其他编辑器)使用 CIX format对这些数据进行编码;你可以 download the Python 3 catalog .不幸的是,对于您的具体示例, datetime.replace() 函数签名尚未充实either:

    <scope doc="Return datetime with new specified fields." ilk="function" name="replace" />
  • 新的 Python 3.5 类型提示语法还需要知道对象期望的参数类型,为此需要为无法自省(introspection)的对象提供 stub 文件。 Python typeshed project提供这些。这包括 datetime module 的所有参数名称。 :

    class datetime:
    # ...
    def replace(self, year: int = ..., month: int = ..., day: int = ..., hour: int = ...,
    minute: int = ..., second: int = ..., microsecond: int = ..., tzinfo:
    Optional[_tzinfo] = None) -> datetime: ...

    您必须自己解析这样的文件;它们不能总是作为尚未定义的 stub 引用类型导入,而不是使用 forward references :

    >>> import importlib.machinery
    >>> path = 'stdlib/3/datetime.pyi'
    >>> loader = importlib.machinery.SourceFileLoader('datetime', path)
    >>> loader.load_module()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<frozen importlib._bootstrap_external>", line 399, in _check_name_wrapper
    File "<frozen importlib._bootstrap_external>", line 823, in load_module
    File "<frozen importlib._bootstrap_external>", line 682, in load_module
    File "<frozen importlib._bootstrap>", line 251, in _load_module_shim
    File "<frozen importlib._bootstrap>", line 675, in _load
    File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 678, in exec_module
    File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
    File "stdlib/3/datetime.pyi", line 12, in <module>
    class tzinfo:
    File "stdlib/3/datetime.pyi", line 13, in tzinfo
    def tzname(self, dt: Optional[datetime]) -> str: ...
    NameError: name 'datetime' is not defined

    您可以通过使用预定义的模块对象和全局变量来解决这个问题,然后迭代名称错误直到它被导入。我将把它作为练习留给读者。 Mypy 和其他类型检查器不会尝试执行代码,它们只是构建一个 AST。

关于Python自省(introspection): get the argument list of a method_descriptor?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42134927/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com