2

I'm developing an application that reads a message input from telegram with a set of variables, and then starts a game with the user. So I created a class that represents an instance of the game, making one game per chat possible:

class Battle:
    def __init__(self, mainchat):
        self.mainchat = mainchat
        print('Instance of battle started on chat %s' % self.mainchat)
    pcount = 0
    team1 = []
    team2 = []
    p1 = ()
    p2 = ()
    p1score = 0
    p2score = 0
    battlechoicep1 = -1
    battlechoicep2 = -1

so, as soon as I get a message, I start an instance of a battle based on user inputes, e.g.

battle = Battle(chat_id)
battle.p1 = 'Paul'
battle.battlechoicep1 = 4
...

this way has been working fine right now, but every time I want to reset the battle, I go through a function that does this:

    battle.pcount = 0
    battle.team1 = []
    battle.team2 = []
    battle.p1 = ()
    battle.p2 = ()
    battle.p1score = 0
    battle.p2score = 0
    battle.battlechoicep1 = -1
    battle.battlechoicep2 = -1
    save() # outside function that saves the scores into a pickle file
    return

So, I would like to make it so this is a function inside my class, so everytime I call battle.reset it would call something like this

def reset():
    battle.pcount = 0
    battle.team1 = []
    battle.team2 = []
    battle.p1 = ()
    battle.p2 = ()
    battle.p1score = 0
    battle.p2score = 0
    battle.battlechoicep1 = -1
    battle.battlechoicep2 = -1
    save() # outside function that saves the scores into a pickle file
    return

I don't know how is the right approach to this problem, I don't even know if what I've been doing up to now is 'correct' (it is working at least). Creating the function inside the class (like def reset(self):) seems to have no effect.

7
  • 4
    You're on the right track with def reset(self), you just need to replace battle with self in the method. Commented Jul 11, 2016 at 19:07
  • @MorganThrapp That is a natural approach -- perhaps you could write it up as an answer. Commented Jul 11, 2016 at 19:09
  • @Bahrom This is why you really shouldn't ever correct the indentation of a Python question. Commented Jul 11, 2016 at 19:13
  • @thebjorn thanks for catching, rolled back with a proper edit. Commented Jul 11, 2016 at 19:13
  • 1
    Is there a reason the variables are class rather than instance variables? Seems like it might be good to associate those with individual battles rather than only have one global set of them. Commented Jul 11, 2016 at 19:16

2 Answers 2

5

You're on the right track with def reset(self). You just need to change the instances of battle to self in the method itself. NOTE: This needs to be a method of the Battle class.

def reset(self):
    self.pcount = 0
    ... # etc
    save() # outside function that saves the scores into a pickle file

When you pass in self as the first parameter of a class method, it allows the method to work on the instance of the class that you've called it on. If you just do def reset(self) without changing the battle to self, it will try to modify a variable in the current scope called battle, which in this case probably doesn't exist.

The other thing you could do if you just want reset to create a completely new object without preserving any of the attributes, you can just do:

def reset(self):
    return Battle()
Sign up to request clarification or add additional context in comments.

3 Comments

I wonder if save() should be save(self) Hard to know without knowing what save is
@John Coleman save() is an outside function that saves the battle results (which is in another function) to the pickle file with the global ranking for those battles. I know the way I wrote it is probably not the best practice, but I'm learning while I develop this project.
@Morgan Thrapp thanks for the answer, the code is working exactly as I wanted now.
0

You're almost there!

class Battle:
    def __init__(self, mainchat):
        self.mainchat = mainchat
        print('Instance of battle started on chat %s' % self.mainchat)
        self.reset()

    def reset(self):
        self.team1, self.team2 = [], []
        self.p1 = self.p2 = ()  #New tuples will be assigned and overwritten
        self.pcount = self.p1score = self.p2score = 0
        self.battlechoicep1 = self.battlechoicep2 = -1
        save() # outside function that saves the scores into a pickle file

So when you need to reset, just call battle.reset()! Maybe the save function can also be a class method as well, just follow the same format.

4 Comments

I just realized, having self.reset() inside the __init__ will execute save() on initialization, not sure if that's intended or not.
It's bad practice to initialize instance variables outside of __init__.
@MorganThrapp, that's an interesting thought that I've never come across. I know that instance variables should all be declared together to keep better track of them. And to not make the mistake of mixing Class-level and Instance-level variables.
Yeah, all of those are good. There's a lot of reasons to make sure you initialize everything in __init__, such as readability. It also makes it much easier to test the class (though that doesn't apply here as much), because you can patch out methods without worrying about attributes not being there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.