Rahul Deora
Rahul Deora

Reputation: 167

Easily pass super class into sub class

If I am writing a code as

class Robot(object):

    def __init__(self, room, position):

        self.position=position
        self.room=room

        self.direction=random.randrange(0,360)

class DuckRobot(Robot):

    def move(self,position2)

        self.position=self.position + position2
        return self.position

Now if I have already created a Robot as r=Robot('My',5) and want DuckRobot to inherit all the arguments how do I do that? simply duck=DuckRobot(r) does not work. Also will the value of self.position in r change if change the value from DuckRobot.(I am planning to have multiple robots so need the base class)

Upvotes: 0

Views: 46

Answers (1)

kindall
kindall

Reputation: 184200

The most obvious way to do it is to just grab the attributes you need from the existing object when creating the new object:

duck = DuckRobot(r.room, r.position)

But this involves a lot of "repeating yourself" and grows to be cumbersome as the number of arguments increases. There are better ways, such as:

  1. Write __init__() to also accept another instance of Robot, and extract the values needed for the new object from that instance.
  2. Write a class method called e.g. from_robot() that accepts another instance, and extracts the necessary values from that.
  3. Write a method that returns the salient attributes for constructing a new instance, and pass those when constructing.

Of these three methods, changing __init__() is pretty much the worst choice, because you need to accept two different sets of values. That means you have to make all arguments optional and add code to make sure a valid combination was passed. So we'll skip that. (You could use functools.singledispatch() to write these variants, but that feature was only added in Python 3.4., and it seems like overkill anyway.)

Here's the class method... method:

class Robot(object):

    def __init__(self, room, position):
        self.position=position
        self.room=room
        self.direction=random.randrange(0,360)

    @classmethod
    def from_robot(cls, robot):
        return cls(robot.room, robot.position)

Now you can construct a DuckRobot from an existing Robot instance r with:

duck = DuckRobot.from_robot(r)

Finally, here's the "return the salient attributes" method. We'll use a property here so you don't have to call it:

class Robot(object):

    def __init__(self, room, position):
        self.position=position
        self.room=room
        self.direction=random.randrange(0,360)

    @property
    def attributes(self):
        return self.room, self.position

Then you can create a new DuckRobot from r like so:

duck = DuckRobot(*r.attributes)

I personally prefer the class method option (alternate constructors are pretty much the #1 use case for class methods) and most Python programmers would have the same preference. If you already want something like the attributes property for another purpose, though, you might as well reuse it.

Upvotes: 3

Related Questions