julka
julka

Reputation: 1242

Parent changing child's attribute

I want to have class-based counter, storing the number of instances created.

It could be implemented as such:

class Parent(object):
    counter = 0
    def __init__(self):
        # remembers the order in which the instances were created
        self.counter = counter
        Parent.counter += 1

And I want to have numerous Child classes doing the same, i.e. each Child class should have a separate counter.

Since the logic is the same, I feel I should be able to increment the child class's counter from the parent's __init__ method, instead of copy-pasting it.

Upvotes: 0

Views: 507

Answers (2)

mgilson
mgilson

Reputation: 310307

Yes, you should be able to increment the child's counter from the parent -- but you've hard-coded the class.

def __init__(self):
    type(self).counter += 1

should do the trick...

>>> class Parent(object):
...   counter = 0
...   def __init__(self):
...     type(self).counter += 1
... 
>>> class C1(Parent): pass
... 
>>> class C2(Parent): pass
... 
>>> C1().counter
1
>>> C1().counter
2
>>> C1().counter
3
>>> C2().counter
1
>>> C2().counter
2
>>> C2().counter
3

Be careful, though... if Parent ever has its counter incremented, then all future children will start at that value.

>>> Parent.counter = 3.14159
>>> class C3(Parent): pass
... 
>>> C3().counter
4.14159

Current children will be unaffected:

>>> C2().counter
4

Upvotes: 2

jonrsharpe
jonrsharpe

Reputation: 122159

One option would be to have a class method for updating the counter:

class Parent(object):

    counter = 0

    def __init__(self):
        self.counter = self.counter  # get the current value of the class attribute
        self.increment_counter()

    @classmethod
    def increment_counter(cls):
        cls.counter += 1


class Child1(Parent):
    pass


class Child2(Parent):
    pass

In use:

>>> c1a = Child1()
>>> c1b = Child1()
>>> c2a = Child2()
>>> Parent.counter
0  # no Parent instances
>>> Child1.counter
2  # two Child1 instances
>>> Child2.counter
1  # one Child2 instance
>>> c2a.counter
0
>>> c1b.counter
1
>>> c2a.counter
0

Note, however, that reusing the name counter for both the number of instances on each class (ClassName.counter) and which number each instance is (instance.counter) makes it harder to access the former from an instance method.

Upvotes: 2

Related Questions