Reputation: 9335
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!
Upvotes: 2
Views: 126
Reputation: 287755
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')
Upvotes: 3
Reputation: 381
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.
Upvotes: 2
Reputation: 298056
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.
Upvotes: 4