python - Python - dir() 中的重复是错误吗?
问题描述
在以下序列中,使用 numpy dir(np) 返回重复条目。这是一个错误吗?dir() 是否允许/预期返回重复项?
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> len(dir(np))
620
>>> np.testing
<module 'numpy.testing' from 'C:\\Python\\Python38\\lib\\site-packages\\numpy\\testing\\__init__.py'>
>>> len(dir(np))
621
>>> [i for i in dir(np) if i == "testing"]
['testing', 'testing']
>>> np.__version__
'1.18.1'
>>>
解决方案
这看起来是一个(相对无害的)错误,由优化引发,numpy
以避免testing
急切地导入子包的费用,同时仍然提供testing
和Tester
作为根numpy
包的属性。
优化使用模块级别__getattr__
(仅在 Python 3.7+ 上可用,因此在 3.6 及更早版本上不使用)仅在显式访问它们时才导入它们(此时testing
成为 的真实属性numpy
,因为子模块和包是作为属性自动附加到它们的父级),但是为了继续假装它们被急切地导入,它还定义了一个模块级__dir__
来假装它们已经存在:
def __dir__():
return list(globals().keys()) + ['Tester', 'testing']
这里的缺陷是,如果numpy.testing
被导入(显式地或通过__getattr__
钩子隐式地导入),那么它已经出现在 中,globals()
因此添加['Tester', 'testing']
到.list
'testing'
dir
他们可以通过重复数据删除(在转换为 之前list
,或者只是省略转换,因为dir
已经记录自动执行转换)来解决这个问题,而不是在之后连接,例如:
def __dir__():
return globals().keys() | {'Tester', 'testing'}
但这不是一个严重的错误;dir
由于产生双倍结果而中断的代码可能从一开始就非常脆弱和错误。
此优化的完整解释在源注释中:
# Importing Tester requires importing all of UnitTest which is not a
# cheap import Since it is mainly used in test suits, we lazy import it
# here to save on the order of 10 ms of import time for most users
#
# The previous way Tester was imported also had a side effect of adding
# the full `numpy.testing` namespace
#
# module level getattr is only supported in 3.7 onwards
# https://www.python.org/dev/peps/pep-0562/
在 3.6 及更早版本中,定义__getattr__
和的代码路径__dir__
被跳过,它所做的只是:
# We don't actually use this ourselves anymore, but I'm not 100% sure that
# no-one else in the world is using it (though I hope not)
from .testing import Tester
这意味着testing
并且Tester
是从一开始的“真实”属性,并且不会出现错误。
推荐阅读
- django - 将自定义 url 操作参数添加到 django-cms
- python - 框架内的 Python 网格管理器
- cakephp - CakePHP 3:[ManyToMany] 使用多个特定标签获取书签
- python - 将同一天的所有数据收集到一行
- listview - 如何在主详细信息页面中添加导航页面?
- python - 创建具有 REAL 值(包括 UNIQUE 约束)的 SQLITE 表的最佳方法是什么?
- php - 未识别的索引错误,数据库中没有结果
- php - 从访问器返回 HTML 是否可以接受?
- gatsby - Gatsby 拒绝安装所有依赖项
- css - CSS动画悬停效果