How to subclass a subclass of numpy.ndarray

2024/9/24 23:30:41

I'm struggling to subclass my own subclass of numpy.ndarray. I don't really understand what the problem is and would like someone to explain what goes wrong in the following cases and how to do what I'm trying to do.

What I'm trying to achieve:

I have a subclass of numpy.ndarry that behaves as I want (class A in the code below). I want to subclass A (class B in the code below) so that B contains additional information (name) and methods (the decorated .simple_data method).

Case 1:

import numpy as npclass A(np.ndarray):def __new__(cls,data):obj = np.asarray(data).view(cls)return objdef __array_finalize(self,obj):if obj is None: returnclass B(A):def __init__(self,data,name):super(B,self).__init__(data)self.name = name@propertydef simple_data(self):return [data[0,:],data[:,0]]if __name__ == '__main__':data = np.arange(20).reshape((4,5))b = B(data,'B')print type(b)print b.simple_data

Running this code produces the output:

Traceback (most recent call last):File "ndsubclass.py", line 24, in <module>b = B(data,'B')
TypeError: __new__() takes exactly 2 arguments (3 given)

I assume that this is related to the 'name' variable in the construction of B and that due to A being a subclass of numpy.array, A's new method is being called before B's init method. Thus to fix this I assume that B also needs a new method that appropriately handles the additional argument.

My guess is something like:

def __new__(cls,data,name):obj = A(data)obj.name = namereturn obj

should do it, but how do I change the class of obj?

Case 2:

import numpy as npclass A(np.ndarray):def __new__(cls,data):obj = np.asarray(data).view(cls)return objdef __array_finalize__(self,obj):if obj is None: returnclass B(A):def __new__(cls,data):obj = A(data)obj.view(cls)return objdef __array_finalize__(self,obj):if obj is None: return@propertydef simple_data(self):return [self[0,:],self[:,0]]if __name__ == '__main__':data = np.arange(20).reshape((4,5))b = B(data)print type(b)print b.simple_data()

When run the output is:

<class '__main__.A'>
Traceback (most recent call last):File "ndsubclass.py", line 30, in <module>print b.simple_data()
AttributeError: 'A' object has no attribute 'simple_data'

This surprises me as I was expecting:

<class '__main__.B'>
[array([0, 1, 2, 3, 4]), array([ 0,  5, 10, 15])]

I assume that the call to view() in B.new() is somehow not correctly setting the class of obj. Why?

I'm confused as to what is going on and would be very grateful if someone could explain it.

Answer

For Case 1, the simplest way is:

class B(A):def __new__(cls,data,name):obj = A.__new__(cls, data)obj.name = namereturn obj

__new__ is actually a static method that takes a class as the first argument, not a class method, so you can call it directly with the class of which you want to create an instance.

For Case 2, view doesn't work in-place, you need to assign the result to something, the simplest way is:

class B(A):def __new__(cls,data):obj = A(data)return obj.view(cls)

Also, you've got __array_finalize__ defined the same in A and B there (probably just a typo) -- you don't need to do that.

https://en.xdnf.cn/q/71646.html

Related Q&A

How to ignore an invalid SSL certificate with requests_html?

So basically Im trying to scrap the javascript generated data from a website. To do this, Im using the Python library requests_html. Here is my code :from requests_html import HTMLSession session = HTM…

Fabric asks for root password

I am using Fabric to run the following:def staging():""" use staging environment on remote host"""env.user = ubuntuenv.environment = stagingenv.hosts = [host.dev]_setup_pa…

Beautifulsoup results to pandas dataframe

The below code returns me a table with the following resultsr = requests.get(url) soup = bs4.BeautifulSoup(r.text, lxml)mylist = soup.find(attrs={class: table_grey_border}) print(mylist)results - it st…

XGBoost CV and best iteration

I am using XGBoost cv to find the optimal number of rounds for my model. I would be very grateful if someone could confirm (or refute), the optimal number of rounds is: estop = 40res = xgb.cv(params, d…

Whats the correct way to implement a metaclass with a different signature than `type`?

Say I want to implement a metaclass that should serve as a class factory. But unlike the type constructor, which takes 3 arguments, my metaclass should be callable without any arguments:Cls1 = MyMeta()…

Python -- Regex -- How to find a string between two sets of strings

Consider the following:<div id=hotlinklist><a href="foo1.com">Foo1</a><div id=hotlink><a href="/">Home</a></div><div id=hotlink><a…

Kivy TextInput horizontal and vertical align (centering text)

How to center a text horizontally in a TextInput in Kivy?I have the following screen:But I want to centralize my text like this:And this is part of my kv language:BoxLayout: orientation: verticalLabe…

How to capture python SSL(HTTPS) connection through fiddler2

Im trying to capture python SSL(HTTPS) connections through Fiddler2 local proxy. But I only got an error.codeimport requests requests.get("https://www.python.org", proxies={"http": …

removing leading 0 from matplotlib tick label formatting

How can I change the ticklabels of numeric decimal data (say between 0 and 1) to be "0", ".1", ".2" rather than "0.0", "0.1", "0.2" in matplo…

How do I check if an iterator is actually an iterator container?

I have a dummy example of an iterator container below (the real one reads a file too large to fit in memory):class DummyIterator:def __init__(self, max_value):self.max_value = max_valuedef __iter__(sel…