对象实例中看似不可变的字典

Seemingly immutable dict in object instance

如果我运行以下cartopy代码:

import cartopy.crs as ccrs
globe = ccrs.LambertCylindrical()
print(globe.proj4_params)
globe.proj4_params['a'] = 5
print(globe.proj4_params)

我得到:

{'proj': 'cea', 'lon_0': 0.0, 'a': 57.29577951308232, 'ellps': 'WGS84'}
{'proj': 'cea', 'lon_0': 0.0, 'a': 57.29577951308232, 'ellps': 'WGS84'}

暗示 proj4_params 属性 是不可变的。

但这只是一个沼泽标准dict:

print(type(globe.proj4_params))

<class 'dict'>

因为它是用 C 实现的,所以不能被覆盖以产生这种行为(至少不安全)。

好的,但是这个 class 的代码是 dead simple,所以我的理解有问题。有人可以向我解释为什么我会出现这种行为吗?

编辑:

以下:

projection.proj4_params = dict(projection.proj4_params)

结果:

*** AttributeError: attribute 'proj4_params' of 'cartopy._crs.CRS' objects is not writable

您可以通过先将其转换为字典来确保您的参数是字典。

params = dict(globe.proj4_params)

那么如果你打印

print type(params)

<type 'dict'>

请注意您问题中的 <type 'dict'> 而不是 <class 'dict'>。您正在使用的字典可能是自定义的 class,它是不可变的,但使用相同的 dict 名称。

proj4_params对象最终定义在Projection's superclass CRS, which is supplied by the private, cython module _crs.pyx within cartopy. When a cartopy CRS'中定义proj4_params,它只是定义为class中的一个变量,而不是作为一个 class 变量(也就是说,它 不是 定义为 self.proj4_params)。这是您无法修改 proj4 参数值的部分原因。

就其价值而言,我相信这是 cartopy CRS 的正确行为方式。每个 CRS 的 proj4_params 元素是对 cartopy 在 Python 中提供的基础投影的规范定义的直接引用。这些规范定义由 proj.4 组织维护(例如 Lambert Cylindrical is here),因此修改 proj4_params 将意味着您的投影 不再是兰伯特圆柱投影 .

如果您特别需要一个几乎 Lambert Cylindrical 的 cartopy CRS,您总是可以通过复制 cartopy 自己的代码来创建自己的 crs LambertCylindrical class.只要您在自己的 class 中维护继承,您就应该能够像使用 cartopy 的内置 CRS 之一一样使用它。请注意,如果您确实为自己的 class 修改了 proj4_params,它可能不起作用,因为您指定的参数与 proj.4 本身中的任何内容都不匹配。在这种情况下,您可以考虑修改 CRS 的 globe 属性以进行所需的投影更改。