python - 了解 `np.ndarray` 子类化中的默认值
问题描述
我正在阅读numpy
有关 subclassing 的文档ndarray
,但在设置默认值方面,我观察到的结果与描述的结果略有不同。该文档似乎说应该使用一个位置来设置额外属性的默认值,但我发现在两个位置保持正确的默认值是必要的。
考虑文档中描述的实际示例,在此处复制(为简洁起见,注释已重新格式化):
import numpy as np
class RealisticInfoArray(np.ndarray):
def __new__(cls, input_array, info=None):
obj = np.asarray(input_array).view(cls)
obj.info = info
return obj
def __array_finalize__(self, obj):
# Note that it is here, rather than in the __new__ method,
# that we set the default value for 'info', because this
# method sees all creation of default objects - with the
# InfoArray.__new__ constructor, but also with
# arr.view(InfoArray).
if obj is None: return
self.info = getattr(obj, 'info', None)
描述默认值生效位置的注释让我感到困惑。我替换了默认值以查看发生了什么,例如:info='michelangelo'
in__new__
和getattr(obj, 'info', 'donatello')
in __array_finalize__
。我发现后者只设置了view
创建方法,而前者用于显式构造函数调用和from-template创建:
>>> a = RealisticInfoArray(np.arange(10)); print(a.info)
michelangelo
>>> b = np.arange(10).view(RealisticInfoArray); print(b.info)
donatello
>>> c = a[1:]; print(c.info)
michelangelo
a
在这种情况下,根据我对文档的阅读,它看起来像是采用了“错误”的默认值。据我所知,a.info
在 中设置正确__array_finalize__
,但随后被默认的 from 覆盖__new__
。
首先,我是不是搞错了?如果没有,我是否需要在两个地方都保持预期的默认值,或者有没有办法将其减少到一个?(我在下面的回答中对此进行了尝试,感谢任何反馈。)
解决方案
我目前的解决方法(除了维护两个默认值)是提供一个类属性 ,DEFAULT_INFO
可以由__new__
和访问__array_finalize__
:
import numpy as np
class RealisticInfoArray(np.ndarray):
DEFAULT_INFO = 'michelangelo'
def __new__(cls, input_array, info=None):
obj = np.asarray(input_array).view(cls)
if info is None:
info = obj.DEFAULT_INFO
obj.info = info
return obj
def __array_finalize__(self, obj):
if obj is None: return
self.info = getattr(obj, 'info', self.DEFAULT_INFO)
正确产生:
>>> a = RealisticInfoArray(np.arange(10)); print(a.info)
michelangelo
>>> b = np.arange(10).view(RealisticInfoArray); print(b.info)
michelangelo
>>> c = a[1:]; print(c.info)
michelangelo
这还有一个额外的好处,即类的用户可以修改默认值(例如RealisticInfoArray.DEFAULT_INFO = 'leonardo'
),并在他们认为合适的时候使用他们自己的默认值。但是,我尚未测试此解决方案的意外副作用。
推荐阅读
- angular - 页面初始角度 4 上的默认数据
- ios - iOS CorePlot:y 轴呈现在错误的位置
- android - Android 横向活动首先以纵向打开,然后切换到横向
- jenkins - 用于针对构建进行编码标准验证的最佳 Jenkins 插件(对于 .NET)
- ruby-on-rails - IntegrationTest 从配置中引发错误?
- angular - Karma 的角度测试错误
- google-apps-script - 以域管理员身份从 Google 课堂检索课程作业资源时出现权限错误
- javascript - KnockoutJS - 将 observableArray 与另一个 observableArray 进行比较
- biztalk - BizTalk 批处理配置筛选器未保存
- spring - 基本 Spring JDBC 应用程序,未找到 JdbcTemplate bean