You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用super().view()时子类dtype setter触发的原因及解决方法

问题解析与解决方案

触发子类dtype setter的原因

调用super().view(np.uint8)时,numpy内部在生成新视图数组的过程中,会自动设置数组的dtype属性。由于你的子类myarray覆盖了dtype的setter方法,而view返回的新对象仍然是myarray类型(view默认保留原数组的类型),所以numpy内部设置dtype的操作会触发你自定义的setter逻辑。

解决方法

方法一:避免覆盖numpy原生dtype属性

numpy的ndarray本身已经内置了dtype属性,强行覆盖会干扰其内部逻辑。建议使用自定义属性名来实现你的需求:

import numpy as np

class myarray(np.ndarray):
    _custom_dtype = None

    def __new__(cls, in_data, dtype):
        obj = np.array(in_data, dtype).view(cls)
        obj._custom_dtype = dtype
        return obj

    def view(self, dtype = None):
        if dtype is None:
            return self
        else:
            return super().view(np.uint8)
    
    @property
    def custom_dtype(self):
        return self._custom_dtype
    
    @custom_dtype.setter
    def custom_dtype(self, value):
        print("Setter for custom_dtype in the child class is called!!")
        self._custom_dtype = value

a = myarray([1, 2, 3, 4], dtype = np.uint16)
b = a.view(dtype = np.uint8)
print(b)

方法二:让view返回原生numpy数组

修改view方法,使其返回原生np.ndarray实例而非子类对象,这样就不会触发子类的setter:

def view(self, dtype = None):
    if dtype is None:
        return self
    else:
        # 先转成原生ndarray再生成视图
        return super().view(np.ndarray).view(np.uint8)

方法三:在setter中过滤内部调用(不推荐)

如果必须保留dtype属性的覆盖,可以在setter中判断是否为numpy内部操作,但这种方法依赖numpy内部实现,后续版本可能失效:

import inspect
import numpy as np

class myarray(np.ndarray):
    __dtype = None

    def __new__(cls, in_data, dtype):
        obj = np.array(in_data, dtype).view(cls)      
        return obj

    def view(self, dtype = None):
        if dtype is None:
            return self
        else:
            return super().view(np.uint8)
    
    @property
    def dtype(self):
        return self.__dtype if self.__dtype is not None else super().dtype
    
    @dtype.setter
    def dtype(self, value):
        # 检查调用栈,跳过numpy内部的调用
        caller_frame = inspect.currentframe().f_back
        caller_module = caller_frame.f_globals.get('__name__', '')
        if not caller_module.startswith('numpy'):
            print("Setter for dtype in the child class is called!!")
        self.__dtype = value

内容的提问来源于stack exchange,提问作者MrAliB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:27:14