Akhil
Akhil

Reputation: 21

How to call the __init__ method of the mothe class?

I have the following error: Error Traceback (most recent call last): line 25,line 14,line 3 AttributeError: 'str' object has no attribute 'Teamname'

Here is my python code:

    class Team:
        def __init__(self,Name = "Name",Origin= "india"):
            self.Teamname = Name
            self.Teamorigin= Origin

        def DefTeamname(self,Name):
            self.Teamname = Name
        def defTeamorigin(self,Origin):
            self.Teamorigin = Origin


    class Player(Team):
        def __init__(self,Pname,Ppoints,Tname,Torigin):
            Team.__init__(Tname,Torigin)
            self.Playername = Pname
            self.Playerpoints = Ppoints

        def Scoredpoint(self):
            self.Playerpoints += 1

        def __str__(self):
            return self.Playername + "has scored" + str(self.Playerpoints) + "points"

    Player1 = Player('Sid',0,'Gokulam','Kochi')
    print(Player1)

What am I doing wrong?

Upvotes: 0

Views: 64

Answers (2)

2e0byo
2e0byo

Reputation: 5964

Your error is being thrown because the first argument to __init__ is being interpreted as self, and __init__ is therefore trying to mutate it. It only works at all because you use keyword arguments, so Origin is just falling back to the default.

Note for completeness that you can call the method directly on the target class (or any other class for that matter), but that self is not bound and you lose the advantage of super() always pointing to the parent in the MRO. This works:

class A:
    def __init__(self, a):
        self._a = a

class B:
    def __init__(self, a, b):
        self._b = b
        A.__init__(self, a)

b = B(6, 7)
assert b._a == 6

Incidentally this shows that __init__ is just a function which takes a muteable first arg (self by convention) and mutates that arg.

You really should use super() however. What happens if I redefine A?:

class newA:
    def __init__(self):
        self._other = True

class A(newA):
    ...

If you have used super() all the way through, everything will work fine:

class NewA:
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

class A(NewA):
    def __init__(self, a=None, **kwargs):
        self._a = a
        super().__init__(**kwargs)

Note the use of keyword arguments to pass up the chain without worrying about the semantics of every class's init.

Further Reading

Upvotes: 2

Cyrille Pontvieux
Cyrille Pontvieux

Reputation: 2471

class Player(Team):
    def __init__(self,Pname,Ppoints,Tname,Torigin):
        super().__init__(Tname,Torigin)
        ...

You cannot call __init__ yourself on the class, you need to call on the instance by using super() notation, else the self parameter will not be bound correctly

Upvotes: 1

Related Questions