Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 具有不同导入策略的可变类属性_Python_Python 3.6 - Fatal编程技术网

Python 具有不同导入策略的可变类属性

Python 具有不同导入策略的可变类属性,python,python-3.6,Python,Python 3.6,我最近偶然发现了可变类属性的一种奇怪行为。 理论上(实际上),在类级别定义的可变参数将在所有实例中共享,直到任何实例覆盖引用为止 在我们的项目中,我们有如下目录结构: ├─── main.py └─── src ├─── __init__.py ├─── cache_user.py └─── common_cache.py 公共_cache.py: cache_user.py: main.py: 运行main.py的结果: 所有ID都与预期的相同,这证明所有实例和类都共

我最近偶然发现了可变类属性的一种奇怪行为。
理论上(实际上),在类级别定义的可变参数将在所有实例中共享,直到任何实例覆盖引用为止

在我们的项目中,我们有如下目录结构:

├─── main.py
└─── src
    ├─── __init__.py
    ├─── cache_user.py
    └─── common_cache.py
公共_cache.py: cache_user.py: main.py: 运行main.py的结果: 所有ID都与预期的相同,这证明所有实例和类都共享对同一字典的公共引用。然而,当我们将
src
目录添加到
PYTHONPATH
并稍微更改导入时,会发生一些奇怪的事情

cache_user.py: main.py 运行main.py的结果: 现在,
CommonCache
(和实例)有了自己的
cache
字典,不同于
CacheUser
(和实例)。怎么搞的?唯一改变的是我们进行导入的方法。若我们将断点放在
CommonCache
类中,我们可以清楚地看到,
cache={}
执行两次-每次导入一次。如果有多个类导入
CommonCache
,则只有不同的导入方法才会触发
cache={}

在我们的项目中解决这个问题不仅仅是统一导入方法,因为项目太大了,无法做到这一点。我们的解决方案是创建只由
CommonCache
导入的
CacheStorage
类,真正的
cache
dict存储在
CacheStorage

那么,为什么会这样?我找不到这种情况的任何解释。
还有,如何处理?有没有比创建
CacheStorage
对象更好的解决方案


这在CentOS和Windows上的Python3.6中进行了测试。

这表明模块是通过其“导入”名称而不是模块文件的绝对文件来标识的。在您的情况下,一个模块
src.common\u cache
位于
中,而另一个模块
common\u cache
位于
/src

。因此,导入了两个不同的模块(Python解释器的想法):

  • 一个
    CommonCache
    在模块
    src.common\u cache
  • 在模块
    common\u cache
    中定义的一个
    CommonCache
此断言还显示
CommonCache
未引用同一类

assert src.common_cache.CommonCache is not common_cache.CommonCache

我认为
src.common_cache
common_cache
虽然指向同一个文件,但它们被认为是不同的模块。为了归档类变量/模块变量的单例模式,应该在相关文件中标准化如何导入模块的名称。但主要的问题是为什么会这样?这很清楚。但是,如果两种情况下的文件路径相同,您能告诉我为什么它会以这种方式工作吗?它是一个bug还是一个特性?如果是功能,用例是什么?这不是bug,也不是功能。这就是导入系统的工作方式。Python首先在内存中搜索所需的,以查看是否已加载。如果没有,Python将在
sys.path
(与
PYTHONPATH
相关)中逐个搜索它,或者提升
importorror
。好吧,但是为什么
src.common\u cache
common\u cache
的目标是同一个文件时,它们会被视为不同的模块呢?您可以在
sys.modules
中看到这一点。这看起来像个虫子。注意,在第一个示例中,import语句只执行一次。永远不会引发
ImportError
,如果同一文件位于
PYTHONPATH
中,它只会导入两次。如果
sys.modules
中的键是完整文件路径而不是相对路径,则两个模块将被视为一个。
from .common_cache import CommonCache


class CacheUser(CommonCache):
    pass
from src.cache_user import CacheUser
from src.common_cache import CommonCache

common_cache = CommonCache()
cache_user = CacheUser()
print(id(common_cache.cache))
print(id(CommonCache.cache))
print(id(cache_user.cache))
print(id(CacheUser.cache))
2163305605304
2163305605304
2163305605304
2163305605304
from src.common_cache import CommonCache


class CacheUser(CommonCache):
    pass
from cache_user import CacheUser
from common_cache import CommonCache

common_cache = CommonCache()
cache_user = CacheUser()
print(id(common_cache.cache))
print(id(CommonCache.cache))
print(id(cache_user.cache))
print(id(CacheUser.cache))
2067930459016
2067930459016
2067930458440
2067930458440
assert src.common_cache.CommonCache is not common_cache.CommonCache