对象实例中看似不可变的字典
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 属性以进行所需的投影更改。
如果我运行以下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 属性以进行所需的投影更改。