Home > database >  python data relationships with classes, can't pass data correctly
python data relationships with classes, can't pass data correctly

Time:08-30

So I had this idea to make a python program that does data relationships by using lists, classes, objects, and some nested for-each loop trickery.

I don't understand how to structure my program with regards to passing data from a class's internal function/method in a way that's usable. 5 years ago I had similar problems with c and I developed a bad habit of calling a function as another function's parameter/argument, like, grabbing a bitmap image via a return function, and putting that function call as a parameter/argument to another function call (seems I had to do that pointer trickery to get an image's data from one code file into another because of my modularisation). Without even studying a compsci course, I knew that my code was sketchy.

Now, in the current project, I want to create a bunch of game titles, and then the platforms, and somehow list a game along with the platforms that the game is on. My program is based on something that I saw in a c# example, but I'm doing this in Python.

Somehow, in the main part of the program, I need to print the game's name along with the platforms that it's available on. I'm trying to add a platform object into a game object's list (adding xbox and playstation into the game, secret weapons over normandy) and then I want to print those platform's strings (their names).

The main program should have a nested for-loop that iterates games and then iterates through their list of platforms and somehow print the platform's name - or vice versa, list games under platforms. It'd be simpler to just have game titles as a list under a platform class object, but games should have their own data and therefore be a class.

How do I go about linking these objects and their data with an object of another class? Is there something I should use instead of lists?

class Game:

    name = ""
    availability = []

    def __init__(self, InputName):
        self.availability = []
        print ("created, "   InputName)
        name = InputName

    def ShowAvailability(self):
        return (iter(self.availability))

class Platform:

    name = ""

    def __init__(self, InputName):
        print "created, "   InputName
        name = InputName

    def GrabName():
        return name

# Game titles
SecretWeapons = Game("Secret Weapons Over Normandy")
Halo = Game("Halo Combat Evolved")
DeathStranding = Game("Death Stranding")

# Platforms
Xbox = Platform("Xbox")
PlayStation = Platform("Playstation")

SecretWeapons.availability.append(Xbox)
SecretWeapons.availability.append(PlayStation)

for i in SecretWeapons.ShowAvailability():
    print (i.GrabName)

Another way NOT to do this:

class Game:

    name = ""
    availability = []

    def __init__(self, InputName):
        self.availability = []
        print ("created, "   InputName)
        name = InputName

    # Prepare to fail...
    def ShowAvailability(self):
        return self.availability

class Platform:

    name = ""
    AvailableGames = []

    def __init__(self, InputName):
        print "created, "   InputName
        name = InputName

    def GrabName():
        return name

# Game titles
SecretWeapons = Game("Secret Weapons Over Normandy")
Halo = Game("Halo Combat Evolved")
DeathStranding = Game("Death Stranding")

# Platforms
Xbox = Platform("Xbox")
PlayStation = Platform("Playstation")

SecretWeapons.availability.append(Xbox)
SecretWeapons.availability.append(PlayStation)

mylist = SecretWeapons.ShowAvailability()

# OOOOFFFFFFF! It won't print the platforms for the game.
for element in mylist:
    print(element)

Finally, trying to pass strings instead of objects. Useless idea because then the data is only linked one-way... but:

SecretWeapons.availability.append(Xbox.name)
SecretWeapons.availability.append(PlayStation.name)

SecretWeapons.ShowAvailability()

Showing the class's function without the init:

class Game:

name = ""
availability = []

def ShowAvailability(self):
    for mystuff in self.availability:
        print(mystuff)

CodePudding user response:

You could do something like this to make both the game objects aware of platforms, and the platform objects aware of games.

Note that unlike in C#, you rarely want to specify fields on the class level (unless you're using dataclasses, which this simple example won't use).

class Game:
    def __init__(self, name):
        self.name = name
        self.platforms = set()

    def add_platform(self, platform):
        if platform not in self.platforms:
            self.platforms.add(platform)
            platform.add_game(self)


class Platform:
    def __init__(self, name):
        self.name = name
        self.games = set()

    def add_game(self, game):
        if game not in self.games:
            self.games.add(game)
            game.add_platform(self)


g1 = Game("Secret Weapons Over Normandy")
g2 = Game("Halo Combat Evolved")
g3 = Game("Mario Kart 8")

xbox = Platform("Xbox")
ps = Platform("Playstation")
switch = Platform("Switch")

g1.add_platform(xbox)
g1.add_platform(ps)
g2.add_platform(xbox)
g3.add_platform(switch)

for plat in (xbox, ps, switch):
    print(plat.name, ":", ", ".join(g.name for g in plat.games))

CodePudding user response:

Create a Platform function within the Game class instead of making Platform a class of it's own. Remember 'self' will keep all values for each object separated.

class Game:
    def __init__(self, inputName):
        self.name = inputName
        self.platforms = []
    def addPlatforms(self, *args):
        for arg in args:
            self.platforms.append(arg)

How to use

SecretWeapons = Game("Secret Weapons Over Normandy")
SecretWeapons.addPlatforms('Xbox', 'Playstation')
for platform in SecretWeapons.platforms:
    print(platform)

# Output
Xbox
Playstation

The reason you're having issues with your code in the first place is because you're not using self at all with the Platform class. Self refers to the object itself. When you're just adding a value to the variable name inside the Platform class, that value has nothing to refer to. Using self.name instead will add the value to the variable name only for the object you're assigning it to.

I personally think you should ditch the Platform class all together. Unless you plan to expand it and add more functions to it, there is no reason to create a class that's only purpose is to assign a value to a variable an return it's value. You can just use variables or lists for that, not classes.

If you want to keep your original code, then here is a functioning version of it.

class Game:
    def __init__(self, InputName):
        self.availability = []
        print ("created, "   InputName)
        self.name = InputName
    def ShowAvailability(self):
        return self.availability

class Platform:
    def __init__(self, InputName):
        print ("created, "   InputName)
        self.name = InputName
    def GrabName(self):
        return self.name

# Game titles
SecretWeapons = Game("Secret Weapons Over Normandy")
Halo = Game("Halo Combat Evolved")
DeathStranding = Game("Death Stranding")

# Platforms
Xbox = Platform("Xbox")
PlayStation = Platform("Playstation")

SecretWeapons.availability.append(Xbox)
SecretWeapons.availability.append(PlayStation)

for i in SecretWeapons.ShowAvailability():
    print (i.GrabName())

Also, remember to add your enclosed brackets when calling GrabName(). Calling it without the enclosed brackets, like you did in your original code, will return back the function itself, not actually execute the function. Another reason why you would have had trouble returning any results back.

  • Related