-1

I'm a freshman in the fantastic world of python and at the moment I'm struggling with this problem... That's an example of what I've coded:

class League():
    def __init__(self, teams=[]):
        self.teams = teams
    def initLeague(self):
        for a in range(2):
            self.teams.append(Team())
            self.teams[a].name = "Team" + str(a)
            for b in range(3):
                self.teams[a].players.append(Player())
                self.teams[a].players[b].name = "Name-" + str(a) + "-" + str(b)
    def printLeague(self):
        for team in self.teams:
            print(team.name)
            for player in team.players:
                print(player.name)

class Team():
    def __init__(self, name=None, players=[]):
        self.name = name
        self.players = players

class Player():
    def __init__(self, name=None):
        self.name = name

nba = League()
nba.initLeague()
nba.printLeague()

The output looks like that:

Team0
Name-1-0
Name-1-1
Name-1-2
None
None
None
Team1
Name-1-0
Name-1-1
Name-1-2
None
None
None
[Finished in 0.051s]

So I would like to know where do these None come from? I noticed they depend on range(n)... it's like if the 'for a' loop is repeating inside the 'for b' loop. Another problem is that the first part of the output should be:

Team0
Name-0-0
Name-0-1
Name-0-2
...

Could someone help me? Thank you!

Lorenzo Fiamingo
  • 3,251
  • 2
  • 17
  • 35
  • The problem is the `players=[]` in `Team` constructor. See https://stackoverflow.com/questions/43255481/python-default-list-in-function/43255920#43255920 – Michael Butscher Nov 25 '18 at 01:22

3 Answers3

1

If you replace your Team() class to this:

class Team():
def __init__(self, name=None):
    self.name = name
    self.players = []

Your output will become this:

Team0
Name-0-0
Name-0-1
Name-0-2
Team1
Name-1-0
Name-1-1
Name-1-2

which I think is what you're after. See this link: "Least Astonishment" and the Mutable Default Argument to see why.

The problem is that when using your current Team() initialiser, the players parameter is not passed with a default value of [] as you are expecting, instead, the value of players is persisted for each team made.

Each team has a reference to the same list, which is why the same list is printed twice.

The reason None is printed three times is because each time a team is created, 3 more players are added, but your inner for loop only modifies the names of the first 3 players, leaving the last 3 players untouched.

0liveradam8
  • 752
  • 4
  • 18
  • That's perfect, but I made the change inside self.teams.append(Team()) that became self.teams.append(Team(player=[])). Thanks for the sample and the link, I get all the story, I found this other link helpful too: http://effbot.org/zone/default-values.htm – Lorenzo Fiamingo Nov 25 '18 at 02:22
1

I agree with 0liveradam8's response and just to add on - if you would like to maintain the constructor signature you could try this:

class Team():
    def __init__(self, name=None, players=None):
        if players is None:
            players = []
        self.name = name
        self.players = players

so you can still specify a list of players in the constructor if necessary.

greenBox
  • 552
  • 4
  • 5
0

The reason you are getting None is that you haven't returned the value in the functions. Therefore, when you run your script, it is set to nothing. Here's a link to look into it more.

http://interactivepython.org/runestone/static/pip2/Functions/Returningavaluefromafunction.html

The answer to your second question is that the

for a in range(2):

Should be like

for a in range(1):

Hope this helps!

Taher A. Ghaleb
  • 5,120
  • 5
  • 31
  • 44
exe
  • 354
  • 3
  • 23