Python自省:获取method_descriptor的参数列表?

abo-abo:

一个代码说明作为我的问题的简介:

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,而我的代码是看它在商务部date.replace(year, month, day)

唯一起作用的内省部分是:

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

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

所以这是问题:

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

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

马丁·彼得斯(Martijn Pieters):

不,您无法获得更多信息;安装C源代码不会使您轻松访问它们。这是因为用C代码定义大多数方法实际上并没有公开这些信息。您必须解析出相当隐秘的C代码

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

re.findall()函数是纯Python函数,因此是自省的。

我说过大多数用C定义的方法,因为从Python 3.4开始,使用新Argument Clinic预处理器的方法将包括一个新__text_signature__属性,内部inspect._signature_fromstr()函数可以对其进行解析。这意味着即使对于这种C定义的方法,您也可以内省参数:

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

另请参见Python 3.4中用于__signature__和__text_signature__的内容

datetime模块尚未收到多少Argument Clinic爱。我们必须耐心等待,或者,如果您真的对此很在意,请提供将模块转换为使用Argument Clinic的补丁。

如果你想看到什么模块具有支持已经,看看Modules/clinic子目录包含生成的诊所输出; 对于该datetime模块,datetime.datetime.now()目前包括在内。该方法定义了一个诊所区

/*[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]*/

使方法自省:

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

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

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

  • Komodo IDE代码情报库(开源,也使用其他编辑器)使用CIX格式对该数据进行编码。您可以下载Python 3目录不幸的是,你的具体的例子,datetime.replace()函数签名尚未充实了两种

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

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

    您必须自己解析这样的文件。不能始终将它们作为尚未定义的存根引用类型导入,而不是使用正向引用

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章