abo*_*abo 21 python introspection
作为我的问题介绍的代码插图:
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
Run Code Online (Sandbox Code Playgroud)
看来,对我来说,只有这样,才能找到的签名datetime.datetime.replace,而我的代码是看它在商务部:date.replace(year, month, day).
唯一可行的内省部分:
datetime.datetime.replace.__doc__
# => 'Return datetime with new specified fields.'
Run Code Online (Sandbox Code Playgroud)
我已经研究了Jupyter函数arglist工具提示是如何工作的,它们有完全相同的问题,即没有可用的arglist datetime.datetime.replace.
所以这里是问题:
是否仍然可以以某种方式得到参数列表?也许我可以安装C源datetime并通过__file__属性连接它们?
是否可以<type 'method_descriptor'>使用arglist信息注释a ?在这种情况下,我可以解析链接文档的markdown定义并自动注释内置模块函数.
不,你无法获得更多信息; 安装C源代码不会让您轻松访问.那是因为C代码中定义的大多数方法实际上并没有公开这些信息; 你必须解析一段相当神秘的C代码:
if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace",
datetime_kws,
&y, &m, &d, &hh, &mm, &ss, &us,
&tzinfo, &fold))
Run Code Online (Sandbox Code Playgroud)
该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, /)>
Run Code Online (Sandbox Code Playgroud)
另请参阅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]*/
Run Code Online (Sandbox Code Playgroud)
使方法内省:
>>> import datetime
>>> inspect.signature(datetime.datetime.now)
<Signature (tz=None)>
Run Code Online (Sandbox Code Playgroud)
没有办法直接将信息附加到那些不可内省的C函数和方法上; 他们也不支持属性.
大多数想要支持此类对象的自动完成解决方案使用单独的数据结构,其中信息是独立维护的(数据的所有固有风险都不同步).其中一些可用于您自己的目的:
Komodo IDE代码智能库(开源,也使用其他编辑器)使用CIX格式对此数据进行编码; 你可以下载Python 3目录.不幸的是,你的具体的例子,datetime.replace()函数签名尚未充实了两种:
<scope doc="Return datetime with new specified fields." ilk="function" name="replace" />
Run Code Online (Sandbox Code Playgroud)新的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: ...
Run Code Online (Sandbox Code Playgroud)
你必须自己解析这样一个文件; 它们不能总是作为尚未定义的存根引用类型导入,而不是使用前向引用:
>>> 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
Run Code Online (Sandbox Code Playgroud)
您可以通过使用预定义的模块对象和全局变量来解决这个问题,然后迭代名称错误,直到它导入为止.我将把它作为读者的练习.Mypy和其他类型的检查器不会尝试执行代码,它们只是构建一个AST.
| 归档时间: |
|
| 查看次数: |
729 次 |
| 最近记录: |