我仍然对Python很陌生,所以请耐心等待。这是我的问题:
我有一个基类,我们称之为体育游戏:
class Game:
def __init__(self):
self.home_team = None
self.away_team = None
我为每项运动都有多个派生类,但我们以棒球为例:
class BaseballGame(Game):
def __init__(self):
self.home_pitcher = None
self.away_pitcher = None
到目前为止一切都很好。但是我在一个单独的python模块中有另一个实用程序功能,它将生成并填充在该运动的给定日期内正在玩的所有游戏的列表。
def fetch_game_data:
games = []
games_found_online = code_that_fetches_online_games
for online_game in games_found_online:
new_game = Game()
new_game.home_team = ...
new_game.away_team = ...
games.append(new_game)
return games
使用BeautifulSoup进行大量解析显然要比这更复杂,但是你明白了。我的问题是这个函数返回一个Base类的列表,但我需要一个Derived类的列表。派生类将是调用此函数来填充列表并对其进行操作的类。我看到它的方式,我有两个选择:
我考虑的另一个选项,但很快就崩溃了,就是将现有的派生类对象列表发送到fetch_game_data函数中,而不是创建新的Game对象,它只会填充现有的对象。问题是我不知道我需要多少游戏对象。 fetch_game_data函数通过解析网页来确定需要多少游戏。我想我可以发送最大数量的游戏,但使用number_of_teams / 2,但如果棒球中有双头怎么办?这很快就崩溃了。我想我可以编写一个函数来获取游戏数据并返回当天的游戏数量。然后我可以填充一个Derived游戏列表,这些游戏的大小和发送量都会被填充。但我必须获取所有网页数据AGAIN并再解析它以填充列表。
只有糟糕的选择!我希望到目前为止还有一个简单而优雅的解决方案。我愿意接受任何建议,包括重新设计,如果有意义的话。
谢谢!
答案 0 :(得分:0)
我正在从c ++移植现有代码,并且遇到了类似的问题。
我有一个通用类X并输入了特定于类的类,例如XInt,XStr等。这些类之间的区别不仅仅是值的类型。在c ++中,这很容易:我有virtual X::compare(X const& other)
。
在XInt中被覆盖。在覆盖方法中,我首先处理“ other”不是XInt的情况,然后执行static_cast<XInt const&>(other)
。
在python中显然是不可能的。所以这是我的解决方案。我添加了一个非虚拟的非公共函数来与XInt进行实际比较,并且没有注释参数的类型:
def _compare(self, other) -> int:
<do-actual-comparison>
def compare(self, other: X) -> int:
<handle cases where other is not XInt>
return self._compare_worker(other)
还没有测试它,但是mypy并没有抱怨,而且由于鸭子在python中键入,它似乎可以工作。也许类似的东西会为您工作。
答案 1 :(得分:0)
您可以在实例类启动后对其进行转换,请参见以下示例:
class A:
def __repr__(self):
return "class A"
def convert(self):
'convert A to B class'
self.__class__ = B
def hello(self):
print('hello from A')
class B(A):
""
def __repr__(self):
return "class B"
def hello(self):
print('hello from B')
a = A()
print(a)
a.hello()
a.convert()
print(a)
a.hello()
# output:
>>> "class A"
>>> "hello from A"
>>> "class B"
>>> "hello from B"
对于您而言,可以在创建实例后将类Game
转换为所需的任何子类。
答案 2 :(得分:-1)
Python无法将对象转换为另一个类(甚至是子类)。
创建游戏对象时必须使用具体类。它可以用工厂方法(例如create_game
)完成,如下所示:
def create_game(online_game):
if online_game.type == 'baseball':
return BaseballGame()
else:
return Game()
def fetch_game_data:
games = []
games_found_online = code_that_fetches_online_games
for online_game in games_found_online:
new_game = create_game(online_game)
new_game.home_team = ...
new_game.away_team = ...
games.append(new_game)
return games