Home > OS >  How is a Python class object instance passed to a function? Are class instances in Python pass by re
How is a Python class object instance passed to a function? Are class instances in Python pass by re

Time:10-24

I don't see any questions on SO regarding this, so I would like to ask how a Python class object instance is passed into a function and how it behaves within the function. I have some suspicions from the behaviour I got from running this snippet:

(Note: I know there are better ways to achieve the same behaviour for this example. My actual use case involves a bit more complicated manouevers :-).

class Animal:
    def __init__(self, name, sound):
        self.name = name
        self.sound = sound

def change_animal(animal_1, animal_2):
    animal_1 = None
    animal_1 = animal_2
    # or better yet,
    # animal_1 = copy.deepcopy(animal_2)

# main
animal_1 = Animal('dog', 'bark')
animal_2 = Animal('duck', 'quack')

change_animal(animal_1, animal_2)
print(animal_1.name)

Prints dog. I always thought it would change the instance and print duck.

Whereas using this:

def change_animal(animal_1, animal_2):
    animal_1.name = animal_2.name
    animal_1.sound = animal_2.sound

Prints duck showing that the instance has been changed?

I wanted to avoid writing anything that requires me to reassign each attribute individually because there is a high likelihood of someone missing a variable and erroneously having a combination of updated and old values.

CodePudding user response:

In python you need to return the value. When calling the function python is making a copy of your animal_1 object and destroying it after the function ends. If you want to change animal_1 you need to return it as the function result.

class Animal:
    def __init__(self, name, sound):
        self.name = name
        self.sound = sound

def change_animal(animal_1, animal_2):
    animal_1 = deepcopy(animal_2)
    return animal_1

# main
animal_1 = Animal('dog', 'bark')
animal_2 = Animal('duck', 'quack')

animal_1 = change_animal(animal_1, animal_2)

The other option is to create the function inside the Animal class.

class Animal:
    def __init__(self, name, sound):
        self.name = name
        self.sound = sound

    def change_animal(self, animal_2):
        self.name = animal_2.name
        self.sound = animal_2.sound

animal_1 = Animal('dog', 'bark')
animal_2 = Animal('duck', 'quack')

animal_1.change_animal(animal_2)

CodePudding user response:

The reason that in the first example the name doesn't change to duck is because of something referred to as scope of a variable. You can read up more on formalities there, so lets keep it simple here:

Put informally, your first function change_animal creates a new variable inside it called animal_1. This variable is not visible outside of change_animal, and is lost when the function ends.

Your second function change_animal indeed takes the animals by reference, and manipulates the objects animal_1 which is visible in the scope of your script.

If you would want (for any reason) to somehow keep the style of your first change_animal function, the example with minimal modifications could look like this:

class Animal:
    def __init__(self, name, sound):
        self.name = name
        self.sound = sound

def change_animal(animal_1, animal_2):
    animal_1 = None
    animal_1 = animal_2
    return animal_1
    # or better yet,
    # animal_1 = copy.deepcopy(animal_2)

# main
animal_1 = Animal('dog', 'bark')
animal_2 = Animal('duck', 'quack')

animal_1 = change_animal(animal_1, animal_2)

print(animal_1.name)
  • Related