Home > Software design >  Creating Distinct Python Objects Using Loop
Creating Distinct Python Objects Using Loop

Time:11-18

I have the following Python code:

from names import get_first_name, get_last_name

class Person(object):
    def __init__(self, first_name=get_first_name(), last_name=get_last_name()):
        self.first_name = first_name
        self.last_name = last_name


def make_group_of_people(num_people):
    people = []
    num = 0
    while num < num_people:
        person = Person(
            first_name=get_first_name(),
            last_name=get_last_name(),
        )
        people.append(person)
        num  = 1
    return people


group = make_group_of_people(3)

for person in group:
    print(f"***NEW PERSON {group.index(person)}***")
    print(person.first_name)
    print(person.last_name)

Which prints out different names, like so:

***NEW PERSON 0***
Christine
Thomas
***NEW PERSON 1***
Orlando
Goff
***NEW PERSON 2***
William
Bedwell

What I don't understand is that when I run this very similar Python code:

from names import get_first_name, get_last_name

class Person():
    def __init__(self, first_name=get_first_name(), last_name=get_last_name()):
        self.first_name = first_name
        self.last_name = last_name
 

def make_group_of_people_2(num_people):
    people = []
    num = 0
    while num < num_people:
        person = Person() ### HERE'S WHAT'S DIFFERENT ###
        people.append(person)
        num  = 1
    return people


same_named_group = make_group_of_people_2(3)

for person in same_named_group:
    print(f"***NEW PERSON {same_named_group.index(person)}***")
    print(person.first_name)
    print(person.last_name)

I get this output, indicating that each object has the first and last names:

***NEW PERSON 0***
Michael
Baylock
***NEW PERSON 1***
Michael
Baylock
***NEW PERSON 2***
Michael
Baylock

What's confusing to me is that I would expect both pieces of code to print out different names, since in both cases the default values for first_name and last_name of the Person class are the results of the random name generator functions of the names package, but clearly that's not what's happening.

I've looked at this question, but it doesn't quite answer what I'm seeing.

Any idea why this is the case? And is this consistent across all OOP languages?

CodePudding user response:

The issue is your constructor:

class Person(object):
    def __init__(self, first_name=get_first_name(), last_name=get_last_name()):
        self.first_name = first_name
        self.last_name = last_name

Default parameter values get evaluated at the time the function is defined (i.e. once), not every time the function is called. (If you stick some logging in get_first_name() you'll see that it's only called once in version 2 of your code.) If you want the defaults to be different each time, do:

class Person:
    def __init__(self, first_name=None, last_name=None):
        self.first_name = first_name or get_first_name()
        self.last_name = last_name or get_last_name()

so that the function calls to get_first_name() and get_last_name() happen each time the function is called without the corresponding parameter.

CodePudding user response:

You have defined the default value for the first name and last name parameters. The default value means that if you do not specify it, it will be selected automatically. See the following code snippet:

from names import get_first_name

default = get_first_name()
print(default)

So when you write:

person = Person()

Default values will be selected.

  • Related