Skip to content
Advertisement

Python: get attribute from class objects stored in an array

I would like to get the attribute of every object contained in an ndarray. Consider the following code, where after vectorization the function returns an ndarray with the objects. From each of these objects in the array, I would like to get the attribute and store the attributes in a new array.

The classes and functions are a dummy for more complex classes and functions. I am aware of the fact that from stud = new_student(["Michael","Rachel"], [1,2]); stud.name I could get a list with the names, however this is not possible with the function I am using instead of new_student.

import numpy as np

class Student: 
      
    # class variable 
    stream = "COE"
      
    # Constructor 
    def __init__(self, name, roll_no): 
          
        self.name = name 
        self.roll_no = roll_no 
        
def new_student(name, roll_no):
    return Student(name, roll_no)

new_student_vec = np.vectorize(new_student)

studArr = new_student_vec(["Michael","Rachel"], [1,2])

studArr.name

Advertisement

Answer

In [3]: class Student:
   ...: 
   ...:     # class variable 
   ...:     stream = "COE"
   ...: 
   ...:     # Constructor 
   ...:     def __init__(self, name, roll_no):
   ...: 
   ...:         self.name = name
   ...:         self.roll_no = roll_no
   ...:     def __repr__(self):
   ...:         return f'Student <{self.name}, {self.roll_no}>'
   ...: 
   ...: 
   ...: def new_student(name, roll_no):
   ...:     return Student(name, roll_no)
   ...: 
   ...: new_student_vec = np.vectorize(new_student)
   ...: 
   ...: studArr = new_student_vec(["Michael","Rachel"], [1,2])
   ...: 

With the added repr the array now prints:

In [4]: studArr
Out[4]: array([Student <Michael, 1>, Student <Rachel, 2>], dtype=object)

When you try name, you get:

In [5]: studArr.name
Traceback (most recent call last):
  File "<ipython-input-5-9248234e8082>", line 1, in <module>
    studArr.name
AttributeError: 'numpy.ndarray' object has no attribute 'name'

You really should have shown this error. Do you understand what’s going on? Just because objects in the array have that attribute, doesn’t mean that the array itself has it.

Consider a list of the same objects. Asking for the name of the list doesn’t make any sense either.

In [6]: alist = studArr.tolist()
In [7]: alist
Out[7]: [Student <Michael, 1>, Student <Rachel, 2>]
In [8]: alist.name
Traceback (most recent call last):
  File "<ipython-input-8-f77eb3c13383>", line 1, in <module>
    alist.name
AttributeError: 'list' object has no attribute 'name'

You still have to ask each element for that attribute:

In [9]: [s.name for s in alist]
Out[9]: ['Michael', 'Rachel']

You could use np.vectorize, as you did with the constructor, to fetch the attributes (or np.frompyfunc), but the results, and timings, are basically the same. Using an object array instead of a list has few, if any, advantages.

The idealize “vectorization” only applies to numeric dtypes. The fast compiled code is written in c using the c numeric types like floats and doubles. Object dtypes require referencing Python objects in the same way as lists.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement