2

I am trying to return a numpy array when calling a class method from a class initialized as a list.

import numpy as np

class test_object:

    def __init__(self, val=1):
        self.value = val

    @staticmethod
    def generate(number=5):

        # create list of test_objects
        obj = [test_object(val=i) for i in range(number)]

        return obj

    def powers(self, pow=2):
        return self.value**pow


numbers = test_object.generate(number=10)

array = np.zeros(len(numbers))

for i in range(len(numbers)):
    array[i] = numbers[i].powers()

print(array)

Is it possible to modify the class / class method 'powers' so, that it will work like:

array = numbers.powers()

The array initializing and the for loop should be done inside the class method.

Aditya Mishra
  • 1,687
  • 2
  • 15
  • 24
JaW.
  • 87
  • 2
  • 11

2 Answers2

2

Here's a solution:

import numpy as np

class test_object():
    def __init__(self, val=1):
        self.value = val

    class test_object_list(list):
        def powers(self):
            return np.asarray([i.powers() for i in self], dtype=float)

    @classmethod
    def generate(cls, number=5):
        # create list of test_objects
        obj = cls.test_object_list([cls(val=i) for i in range(number)])
        return obj

    def powers(self, pow=2):
        return self.value**pow


numbers = test_object.generate(number=10)
array = numbers.powers()
print(array)

Note that I've replaced @staticmethod with @classmethod, as it is more appropriate.

Sagar Gupta
  • 1,352
  • 1
  • 12
  • 26
  • Seems to work, but actually needs a second class to fulfill this task.. A solution where this is squeezed into one class isn't possible? – JaW. Aug 16 '19 at 10:54
  • @JaW. 'Squeezed' in one class now. – Sagar Gupta Aug 16 '19 at 11:12
  • @JaW. Also, I would like to know the purpose of the list of class objects you are keeping, do you have further use for that, or are you just interested in the final numpy array? – Sagar Gupta Aug 16 '19 at 12:34
  • It will be part of a bigger class, with different methods. For some specific ones I need just a final numpy array. – JaW. Aug 19 '19 at 07:29
  • There really is no advantage to nesting he `test_object_list` inside the `test_object` class. Python has no concept of privacy or giving a nested class privileged access, and it is simply clearer to put classes next to one another. – Martijn Pieters Aug 19 '19 at 14:04
0

I believe you need to extend the list functions.

A possible solutions could be the following:

# Extended subclass
class mylist(list):
    def power(self, pow=2):
        if self:
            return[i.value**pow for i in self]


class test_object:

    def __init__(self, val=1):
        self.value = val

    @staticmethod
    def generate(number=5):
        # create list of test_objects
        obj = [test_object(val=i) for i in range(number)]
        obj=mylist(obj)
        return obj

    def powers(self, pow=2):
        return self.value**pow



numbers = test_object.generate(number=10)
print(numbers.power())

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

This answer is also based on another post: Can I add custom methods/attributes to built-in Python types?

Fabrizio
  • 927
  • 9
  • 20
  • This is not returning a numpy array. Also 'numbers' doesn't contain a list 'test_object' anymore which the OP might be needing. – Sagar Gupta Aug 15 '19 at 10:29
  • The first objection is fixed by using numpy.array. The second is not very clear. In your case writing type(numbers) returns test_object_list, type(numbers[0]) object_list. In my case it's similar: type(numbers) returns my_list, type(numbers[0]) object_list. – Fabrizio Aug 15 '19 at 10:54
  • you are right!! But I don't understand how your class has object_list array held inside, it is not very clear with your code, as it is with my implementation, as I am actually keeping a copy in the wrapper class. Now I'm wondering why I even did that. But I still can't understand this phenomena. Can you please explain or direct me to a link? – Sagar Gupta Aug 15 '19 at 11:04