2

I have a Game class which has a field that's a Board object. I currently make a Game by passing in a string encoding information about the game and making the Board object.

However, I now have a bunch of Board objects and want to make a new constructor that takes in the Board object directly.

Here's my current constructor:

def __init__(self, game_string):
    self.single_list = game_string.split(",")
    self.board = self.parse_game_string(game_string)
    self.directions = self.get_all_directions()
    self.red_number_of_streaks = self.get_number_of_streaks("R")
    self.black_number_of_streaks = self.get_number_of_streaks("B")

But now I have the board object, so I'd like to just do:

def __init__(self, board):
    self.board = board
    self.directions = self.get_all_directions()
    self.red_number_of_streaks = self.get_number_of_streaks("R")
    self.black_number_of_streaks = self.get_number_of_streaks("B")

I don't think Python will know how to distinguish between these two constructors. I could determine what to do based on the type of argument? Something like:

if isinstance(str): # usual constructor functionality elif isinstance(Game): # new constructor functionality

Is there a better way?

Thanks!

3 Answers 3

4

I would do it like this:

class Game:
    def __init__(self, board):
        ...

    @classmethod
    def from_string(cls, game_string):
        board = cls.parse_game_string(game_string)
        game = cls(board)
        game.something = 5

        return game

    @staticmethod
    def parse_game_string(game_string):
        ...

        return Board(...)

Game.from_string would then construct an instance of Game out of a string, using the default Game initializer which accepts a Board object.

You will have to make Game.parse_game_string a static method for it to be usable from the Game.from_string class method.

Sign up to request clarification or add additional context in comments.

Comments

3

Looking at the type of input is certainly an option:

class Game(object):
    def __init__(self, str_or_board):
        if isinstance(str_or_board, Board):
            board = str_or_board
        else:
            board = self.parse_game_string(str_or_board)

        self.board = board

Instead of isinstance, duck typing is also an option.

Alternatively, you can use a factory function:

class Game(object):
    def __init__(self, board):
        assert isinstance(board, Board)
        self.board = board

    @classmethod
    def fromstring(cls, board_str):
        return cls(self.parse_game_string(board_str))

# Use like ...
game1 = Game(Board())
game2 = Game.fromstring('foobar')

Comments

2

For method overloading in Python, you can pass both arguments (game_string, board) to the __init__ initializing them as None.

You can then have one constructor such as:

def __init__(self, game_string=None, board=None):
    self.single_list = game_string.split(",")
    self.board = self.parse_game_string(game_string) if game_string else board
    self.directions = self.get_all_directions()
    self.red_number_of_streaks = self.get_number_of_streaks("R")
    self.black_number_of_streaks = self.get_number_of_streaks("B")

If game_string is provided it will be used as the board. Otherwise, the board argument will be used.

Comments

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.