如果存在__getattr__方法,我如何将我创建的对象存储在np.array中?

huangapple go评论60阅读模式
英文:

How do I store objects I created in np.array if a __getattr__ exists?

问题

我为图像处理创建了一个Pixel类(并学会了如何构建一个类)。一个完整的图像是一个由Pixel组成的2D numpy.array,但当我添加了一个__getattr__方法时,它停止工作,因为numpy需要一个__array_struct__属性。

我尝试在__getattr__中添加以下内容:

if name == '__array_struct__':
    return object.__array_struct__

现在它可以工作,但我会收到以下警告:

DeprecationWarning: An exception was ignored while fetching the attribute '__array__' from an object of type 'Pixel'. With the exception of 'AttributeError' NumPy will always raise this exception in the future. Raise this deprecation warning to see the original exception. (Warning added NumPy 1.21)

类的一部分:

class Pixel:
    def __init__(self,*args):

        #用于确定RGB的内容
        self.R,self.G,self.B = RGB
        
        #R,G,B在0到255之间
    ...

    def __getattr__(self,name):
 
        if name == '__array_struct__':
            return object.__array_struct__
        if name[0] in 'iI':
            inted = True
            name = name[1:]
        else:
            inted = False
 
        if len(name) == 1:
            n = name[0]

            if n in 'rgba':
                value = min(1,self.__getattribute__(n.upper())/255)
       
            elif n in 'RGBA':
                value = min(255,self.__getattribute__(n))
                assert 0 <= value
            else:
                h,s,v = rgb_hsv(self.rgb)
                if n in 'h':
                    value = h
                elif n == 's':
                    value = s
                elif n == 'v':
                    value = v
                elif n == 'S':
                    value = s*100
                elif n == 'V':
                    value = v*100
                elif n == 'H':
                    value = int(h)
            if inted:
                return int(value)
            else:
                return value
        else:
            value = []
            for n in name:
                try:
                    v = self.__getattribute__(n)
                except AttributeError:
                    v = self.__getattr__(n)
                if inted:
                    value.append(int(v))
                else:
                    value.append(v)
            return value
英文:

I created a Pixel class for image processing (and learn how to build a class). A full image is then a 2D numpy.array of Pixel but when I added a __getattr__ method , it stopped to work, because numpy wants an __array_struct__ attribute.

I tried to add this in __getattr__:

if name == &#39;__array_struct__&#39;:
    return object.__array_struct__

Now it works but I get

'''DeprecationWarning: An exception was ignored while fetching the attribute __array__ from an object of type 'Pixel'. With the exception of AttributeError NumPy will always raise this exception in the future. Raise this deprecation warning to see the original exception. (Warning added NumPy 1.21)

I = np.array([Pixel()],dtype = Pixel)&#39;&#39;&#39;

a part of the class:

class Pixel:
    def __init__(self,*args):

        #things to dertermine RGB
        self.R,self.G,self.B = RGB
        
        #R,G,B are float between 0 and 255
    ...
    def __getattr__(self,name):
 
        if name == &#39;__array_struct__&#39;:
            return object.__array_struct__
        if name[0] in &#39;iI&#39;:
            inted = True
            name = name[1:]
        else:
            inted = False
 
        if len(name)==1:
            n = name[0]

            if n in &#39;rgba&#39;:
                value = min(1,self.__getattribute__(n.upper())/255)
       
            elif n in &#39;RGBA&#39;:
                value = min(255,self.__getattribute__(n))
                assert 0&lt;=value
            else:
                h,s,v = rgb_hsv(self.rgb)
                if n in &#39;h&#39;:
                    value = h
                elif n == &#39;s&#39;:
                    value = s
                elif n == &#39;v&#39;:
                    value = v
                elif n == &#39;S&#39;:
                    value = s*100
                elif n == &#39;V&#39;:
                    value = v*100
                elif n == &#39;H&#39;:
                    value = int(h)
            if inted:
                return int(value)
            else:
                return value
        else:
            value = []
            for n in name:
                try:
                    v = self.__getattribute__(n)
                except AttributeError:
                    v = self.__getattr__(n)
                if inted:
                    value.append(int(v))
                else:
                    value.append(v)
            return value


</details>


# 答案1
**得分**: 1

在一个类方法中如果你需要一个回退操作可以回退到`super()`代理的**相同方法**

```python
import numpy as np

class Pixel:
    def __init__(self, value):
        self.value = value

    def __getattr__(self, name):
        print(f"{name!r} was requested for {self}")
        return super().__getattr__(name)

I = np.array([Pixel(1), Pixel(2)], dtype=Pixel)
'__array_struct__' was requested for <__main__.Pixel object at 0x7f6ccc40e970>
'__array_interface__' was requested for <__main__.Pixel object at 0x7f6ccc40e970>
'__array__' was requested for <__main__.Pixel object at 0x7f6ccc40e970>
'__array_struct__' was requested for <__main__.Pixel object at 0x7f6ccc40e910>
'__array_interface__' was requested for <__main. Pixel object at 0x7f6ccc40e910>
'__array__' was requested for <__main__. Pixel object at 0x7f6ccc40e910>
英文:

When you are in a class method and want a fallback, fall back to the same method on the super() proxy:

import numpy as np


class Pixel:
    def __init__(self, value):
        self.value = value

    def __getattr__(self, name):
        print(f&quot;{name!r} was requested for {self}&quot;)
        return super().__getattr__(name)


I = np.array([Pixel(1), Pixel(2)], dtype=Pixel)
&#39;__array_struct__&#39; was requested for &lt;__main__.Pixel object at 0x7f6ccc40e970&gt;
&#39;__array_interface__&#39; was requested for &lt;__main__.Pixel object at 0x7f6ccc40e970&gt;
&#39;__array__&#39; was requested for &lt;__main__.Pixel object at 0x7f6ccc40e970&gt;
&#39;__array_struct__&#39; was requested for &lt;__main__.Pixel object at 0x7f6ccc40e910&gt;
&#39;__array_interface__&#39; was requested for &lt;__main__.Pixel object at 0x7f6ccc40e910&gt;
&#39;__array__&#39; was requested for &lt;__main__.Pixel object at 0x7f6ccc40e910&gt;

答案2

得分: 1

你的类应该在numpy尝试获取它时要么实现__array__,要么引发AttributeError。警告消息表示你引发了其他错误,并且numpy将来将不接受这种情况。我还没有完全弄清楚你的代码,但可能是在__getattr__内部调用self.__getattr__(n)会导致最大递归错误。

object.__array_struct__不存在,所以光靠运气,它的AttributeError异常是numpy正在寻找的。更好的策略是对于不符合自动生成属性的选择标准的任何情况都引发AttributeError。然后你可以去掉对__array_struct__的特殊情况,因为它本身也无法正常工作。

英文:

Your class should either implement __array__ or raise an AttributeError when numpy tries to get it. The warning message says you raised some other error and that numpy will not accept that in the future. I haven't figured out your code well enough to know, but it could be that calling self.__getattr__(n) inside of __getattr__ hits a maximum recursion error.

object.__array_struct__ doesn't exist and so just by luck its AttributeError exception is what numpy was looking for. A better strategy is to raise AttributeError for anything that doesn't meet the selection criteria for your automatically generated attributes. Then you can take out the special case for __array_struct__ that doesn't work properly anyway.

huangapple
  • 本文由 发表于 2023年2月6日 02:15:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75354472.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定