1

I'm working on a project, and I have a team class made up of different player classes.

I want a function to create new players and add them to the team, but instead of naming the new player class something like newPlayer(), I want the class name to be the name of the player, so I don't run into issues if I create multiple new players and have a team of the same newPlayer()'s

For example, I want a function like this:

def createPlayer(player_name, player_skill):
    class player_name:
        skill = playerskill
    player_name = player_name()

So if I run:

createPlayer('Mike', 10)

I will get a class named Mike, and I can get Mike's speed with team.Mike.speed

Is it possible to get something like this?

martineau
  • 119,623
  • 25
  • 170
  • 301
Fowl
  • 11
  • 1
  • 1
    This sounds like a bad approach to me. You might want to look into classes and inheritance for a better solution. – SuperKogito Apr 10 '19 at 19:07
  • Dynamically creating variables is a bad idea. See, for example, [Why you don't want to dynamically create variables](http://stupidpythonideas.blogspot.com/2013/05/why-you-dont-want-to-dynamically-create.html) and [How can you dynamically create variables via a while loop?](https://stackoverflow.com/questions/5036700/how-can-you-dynamically-create-variables-via-a-while-loop). – martineau Apr 10 '19 at 20:06

4 Answers4

1

You shouldn't define the class in the function; you define the function as one of the class's methods (namely, __init__):

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

player = Player("Mike", 10)

You define the class once, and create multiple instances of class.

chepner
  • 497,756
  • 71
  • 530
  • 681
1

You could define a dictionary with the name as key.

team = {}
team["Mike"] = create_player("Mike",10)

Now if you run

team["Mike"]

you will get Mike

Syrius
  • 941
  • 6
  • 22
1

NamedTuples might be a cleaner example

>>> from collections import namedtuple
>>> Player = namedtuple('MyPlayer', 'name skill')
>>> Player('Joe', 20)
MyPlayer(name='Joe', skill=20)
>>> jim = Player('Jim', 99)
>>> jim.skill
99

If you are just dead set on using dynamic classes then they are pretty simple to generate at runtime.

>>> Joe = type('Joe', (object,), {'skill': 20})
>>> Joe.skill
20
JBirdVegas
  • 10,855
  • 2
  • 44
  • 50
1

Even though I agree with @chepner, you can indeed create classes at runtime:

def createPlayer(player_name, player_skill):
    return type(player_name, (), {'skill': player_skill})

Mike = createPlayer('Mike', 10)
player = Mike()
print(player.__class__, player.skill)  # <class '__main__.Mike'> 10

Note: Mike = createPlayer('Mike', 10) is equivalent to:

class Mike:
    skill = 10

i.e. skill is a class attribute, not an instance attribute as can be seen with the following snippet:

def createPlayer(player_name, player_skill):
    return type(player_name, (), {'skill': player_skill})

Mike = createPlayer('Mike', 10)
print(Mike.skill)  # 10

player1 = Mike()
player2 = Mike()

print(player1.skill, player2.skill, Mike.skill)  # 10 10 10
player1.skill = 20
print(player1.skill, player2.skill, Mike.skill)  # 20 10 10

A quick Google search for "metaclass" might give you some more extensive sources (e.g. this or this).

Michael H.
  • 3,323
  • 2
  • 23
  • 31