0

I can't seem to find a set of search keywords that provide an answer to this question. I'd like to create a parent class in which a method that uses a class attribute is defined. The child classes will define the values of the class attribute for that child class, using it when calling the method defined in the parent class. How can I do this?

[EDIT: Why do I want to do this? Note that yes, I could create an instance attribute that accomplishes the behavioral goal as shown below. But I want to do this with a class attribute because the code below is just toy example. In my production code I will be creating many thousands of instances of the child classes, and the attribute itself is a large array of data. To my understanding, if I use an instance class it would be a huge waste of memory.]

For example, I want something like this:

class Parent:
    multiplier = None
    def use_it(self, x):
        return Parent.multiplier * x

class Boy(Parent):
    multiplier = 2


class Girl(Parent):
    multiplier = 3


boy = Boy()
print(boy.use_it(10))

girl = Girl()
print(girl.use_it(10))

That would produce this output:

20
30

The traceback:

TypeError                                 Traceback (most recent call last)
~/scratch/test.py in <module>
     13 
     14 boy = Boy()
---> 15 print(boy.use_it(10))
     16 
     17 girl = Girl()

~/scratch/test.py in use_it(self, x)
      2     multiplier = None
      3     def use_it(self, x):
----> 4         return Parent.multiplier * x
      5 
      6 class Boy(Parent):

TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

Futhermore, if I try to redefine the class attribute when definining the child attribute, it redefines it for all classes that inherit from that parent, not just that specific child class. See this example:

class Parent:
    multiplier = None
    def use_it(self, x):
        return Parent.multiplier * x

class Boy(Parent):
    Parent.multiplier = 2


class Girl(Parent):
    Parent.multiplier = 3


boy = Boy()
print(boy.use_it(10))

girl = Girl()
print(girl.use_it(10))

Output:

30
30
6
  • Please update your question with the full error traceback. Commented Jun 3, 2021 at 15:12
  • The code you have shown does exactly what you asked for. You just need to add the missing self parameter to use_it and access multiplier as self.multiplier. Did you try your code before asking? Commented Jun 3, 2021 at 15:20
  • I've expanded on my question, fixed a couple types, added tracebacks, and explained why I want to do what I'm trying to do. Kemp, I'm not lazy. I've tried many variations of the code. I accidentally left out the self argument in the use_it() toy example (and corrected that in the original post). But changing multiplier to self.multiplier is not the solution, as that creates an instance attribute, not a class attribute (actually, it creates an error, since it isn't contained in a __init__() method). Commented Jun 3, 2021 at 15:56
  • Ok, so using self.multiplier is the way to go (see my answer). It does not create an instance attribute unless you write to it. Commented Jun 3, 2021 at 15:58
  • Ahhh. Nice. Thanks, quamrana and Kemp! Commented Jun 3, 2021 at 15:59

1 Answer 1

1

Ok, so you made a few mistakes. I would say that your first revision of the question was closer to working. This is what you want:

class Parent:
    def use_it(self, x):
        return self.multiplier * x

class Boy(Parent):
    multiplier = 2


class Girl(Parent):
    multiplier = 3


boy = Boy()
print(boy.use_it(10))


girl = Girl()
print(girl.use_it(10))

Output

20
30

Note how you don't need to define multiplier for the Parent class because you intend for every derived class to define one itself.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.