0

Suppose I have two arrays that may look something like this

import numpy as np

theta_a = np.array([[-4.0, -3.8, -3.9, -4.0, -4.0, -4.0, -5.0, -6.0, -8.0, -10.0], 
                    [-4.1, -3.9, -3.8, -4.1, -4.0, -4.2, -4.8, -6.2, -8.1, -10.1], 
                    [-3.9, -3.6, -3.7, -3.8, -4.1, -4.0, -4.9, -6.0, -8.2, -9.90]])
theta_b = np.array([[-0.5, -0.6, -0.5, -0.5, -0.7, -0.6, -0.9, -1.0, -1.1, -6.0], 
                    [-0.4, -0.9, -0.8, -0.6, -0.7, -0.8, -1.0, -1.0, -1.1, -6.1], 
                    [-0.4, -0.7, -0.7, -0.8, -0.8, -0.7, -0.9, -1.1, -1.2, -5.9]])

I would like to perform an iterator operation on these lists, and I am able to do so by

d_theta_zip = [b - a for a, b in zip(theta_a, theta_b)]
f_theta_zip = np.tan(np.deg2rad(d_theta_zip))

However, for the sake of curiosity (I have yet to dive into the world of classes) and also to clean up my code a bit, I would like to define a class that does exactly the same

class Tester:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __call__(self):
        d_theta = self.b - self.a
        f_theta = np.tan(np.deg2rad(d_theta))
        return f_theta

This works perfectly fine, once I set it up like this

test = Tester(theta_a[0][0], theta_b[0][0])

which provides the exact same result as

print(f_theta_zip[0][0])

That being said, I am unable to figure out a way to iterate through the class using something like

test_2 = [Tester(a, b) for a, b in zip(theta_a, theta_b)]

and I end up getting the following error message

TypeError: 'list' object is not callable
  • Is there an elegant way of doing this using a class?

As I said, I am doing this as an exercise to get to know the class system better.

naughty_waves
  • 265
  • 1
  • 13
  • 1
    always put full error message (Traceback) in question (as text, not screenshot). There are other useful information. – furas Apr 17 '19 at 10:58
  • as for me you have problem in different place but you didn't show full Traceback to confirm this. – furas Apr 17 '19 at 11:01
  • I tested code which you show in question and I have no problem to get `test_2[0].a`, `test_2[0].b` or `test_2[0]()`. It seems you have problem in different place which you didn't show. Read full Traceback to see where is your problem. – furas Apr 17 '19 at 11:03
  • you don't interate through class `Tester` - you iterate through values from `zip()`. To iterate through class you would have to do `for item in Tester(...)` but you keep single element in this class and there is nothing to iterate - you don't neet iterate it. – furas Apr 17 '19 at 11:09
  • I am sorry, I am a bit new to all of this. @Sanyash answer from below actually solved my issue -- adding `()` after the `Tester` (i.e. `Tester(a, b)()`) slipped my mind. Thank you (or dziękuję bardzo) for setting me straight though. :) – naughty_waves Apr 17 '19 at 13:05
  • You are welcome (PL: proszę bardzo) – furas Apr 17 '19 at 13:13

1 Answers1

3

Looks like you are doing test_2() to invoke Tester.__call__ but instead of this you need to put parentheses after each instance of Tester here:

test_2 = [Tester(a, b)() for a, b in zip(theta_a, theta_b)]
print(test_2)  # [array([0.06116262, 0.05590868, 0.05941095, ...
sanyassh
  • 8,100
  • 13
  • 36
  • 70
  • For the matter this puts all the results for `Tester.__call__` into a list, which is different than putting Tester objects in the list. Point is, for the OP's information, I'm not sure if using a whole Class could be that handy or as readable as just using a `def` function. – lucasgcb Apr 17 '19 at 11:15
  • Thank you, @Sanyash. This is what I wanted. I am a bit of a novice, so I wanted to play around with the `class` option. I also suspect that `def` is more suited for this particular example, but thank you as well for pointing it out, @lucasgcb. :) – naughty_waves Apr 17 '19 at 13:07