Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Fix the Bug

00:00 Let’s go ahead and finally fix this bug in the .move() method. So scrolling up here, I can see that the issue is the order of my conditional statements here.

00:12 I actually need to check whether the location is full before I remove the animals from there, because that’s what’s happening. The animal gets removed from the field before checking whether the location is full. This is why it exits the location that it’s currently in, even if the barn is full. In that case, it’s the order here.

00:34 So I want to move the check of whether the location is full

00:39 before that.

00:42 And because both of these conditional statements here have return statements at the end, so they end the method call if the conditional statement evaluates to True, I don’t actually need to do these as elif.

00:56 So I will also take off the elif to make that a little clearer and add this space in between. That, for me, visually makes it more clear that we have three individual checks that each mean something different.

01:11 The first one checks whether the location you’re trying to move it to is the location that it’s already in. And in that case, no need to run anything else from the method. return, get out of here.

01:24 Same check is if the new location is full. If the new location is full, all you want to do is tell the user that the new location is full. You don’t want to change anything. That was the issue that we had, right?

01:36 And then only if these two checks don’t catch, if both of these return False, then we want to check also if the ._location object is not None.

01:48 Is it actually somewhere at the moment, or is it in the void? If it’s somewhere, then you want to remove it. And this is independent from the first two checks, which is a little more clear if you have them as separate conditional statements. All right, and then the rest should just stay the way it is.

02:08 Whether or not you removed it from the previous location, you want to assign the new location as the current location, and then you want to append it to the new location and return a little logging message that gives this information. That should be the fix.

02:25 So now if I go ahead and run this code,

02:30 then we get the desired output that the pig is still in the field, and the field now also still contains the pig object. And this was my code running this couple of setup and checks that I added at the bottom of the script to make sure that I can test this.

02:50 So we fixed that little subtle bug that was in there. But what you also did is to start writing some automated tests. The code that you wrote down here just checks for something specific.

03:04 It just, again, does it somewhat visually by giving you some output. And it only works because I know what I’m expecting to see here. But this setup code, for example, is an interesting piece that you could carry forward.

03:16 Every time you want to test a method in your code, you’re probably going to need some sort of field, some sort of barn, and some sort of animals. Then maybe you need to fill the barn in a specific test and then move the pig, et cetera.

03:29 So you could reuse quite a bit of the code that you wrote down here if you move these to actually start implement some automated testing.

03:39 But that’s a different story, just a suggestion for you if you want to continue with that. Otherwise, you can also just get rid of it now and be happy that now your farm code is bug free, hopefully.

03:57 Here we got the solution for the bug hunt side quest again. This is the updated .move() method, where you’ve swapped the order of checking whether the new location is full, moving it before you actually remove the animal from the current location.

04:13 And that fixed it. You also cleaned it up a bit by adding white space and just making them separate conditional statements. All right, with this we’re at the end of the course, and in the next lesson I’ll give you a quick recap and then a few more resources that you can use to continue your object-oriented learning journey.

alphafox28js on Dec. 1, 2023

I could use some assistance with the Move Method as it is not allowing me to return anything and give a TypeError: str not callabe....

I have skimmed through everything and am stuck

    @property
    def location(self):
        return self.location.location_type if self.location is not None else 'void'

    def move(self, new_location):
        if self._location is new_location:
            return f"{self.breed} is already here."

        if new_location.is_full:
            return f"{new_location.location_type} is full."

        if self._location is not None:
            self._location.animals.remove(self)

        self._location = new_location
        new_location.animals.append(self)
        return f"{self.breed} move to the {new_location.location_type}"

Martin Breuss RP Team on Dec. 6, 2023

@alphafox28js your .location property is currently referencing itself instead of the non-public ._location attribute. Try this instead:

class Animal: 
    # ...

    @property
    def location(self):
        return self._location.location_type if self._location is not None else "void"

alphafox28js on Dec. 7, 2023

So I made the changes, however, when I go to instantiate and “move” the dog to the field… It still throws a <TypeError: ‘str’ object not callable>…I apologize for this, a bit frustrated as to where the bug is since i have followed along and taken notes each step of the path.

    # Move Method:
    @property
    def location(self):
        return self._location.location_type if self._location is not None else 'void'

    def move(self, new_location):
        if self._location is new_location:
            return f"{self.breed} is already here."

        if new_location.is_full:
            return f"{new_location.location_type} is full."

        if self._location is not None:
            self._location.animals.remove(self)

        self._location = new_location
        new_location.animals.append(self)
        return f"{self.breed} move to the {new_location.location_type}"
field = Field(4)
Pitbull.move(field)

So, now i must ask…does the Move Method need to be in the Parent, or in the Child class as I have it curretnly in the Parent

alphafox28js on Dec. 7, 2023

Also worth noting, the <self._location.location_type>…, states as follows: (function) location_type: Unknown…did i miss adding this in somewhere in a previous video? if I did, it was missed along the way

Martin Breuss RP Team on Dec. 7, 2023

@alphafox28js hm… not sure and it’s a bit hard to say without seeing your full code. It looks like the bug is probably somewhere else in your code.

I’ve implemented the .move() method in the Animal (parent) class as well. If you implemented it in a child class, then you could only move instances of that specific child class.

You can download the example code that I wrote from the Supporting Material drop-down right under the video and compare to your solution. Maybe that can help you find the bug.

Become a Member to join the conversation.