我在一个模块里有很多类。让我们说:
'''players.py'''
class Player1:
def __init__(self, name='Homer'):
self.name = name
class Player2:
def __init__(self, name='Barney'):
self.name = name
class Player3:
def __init__(self, name='Moe'):
self.name = name
...现在,在另一个模块中,我希望动态加载players.py中的所有类并实例化它们。为此,我使用python inspect模块。
'''main.py'''
import inspect
import players
ai_players = inspect.getmembers(players, inspect.isclass)
# ai_players is now a list like: [('Player1',<class instance>),(...]
ai_players = [x[1] for x in ai_players]
# ai_players is now a list like: [<class instance>, <class...]
# now let's try to create a list of initialized objects
ai_players = [x() for x in ai_players]我希望ai_players是像这样的对象实例列表(假设__str__返回名称):['Homer', 'Barney...]
但是,我得到以下错误
TypeError: __init__() takes exactly 2 arguments (1 given)有趣的是,当我没有在列表理解或for循环中实例化类对象时,一切都很好。
# this does not throw an error
ai_player1 = ai_players[0]()
print ai_player1
# >> 'Homer'那么,为什么Python不允许我实例化列表理解/ for循环中的类(我也在for循环中尝试过)?
或者更好的方法:如何动态加载模块中的所有类并在列表中实例化它们?
*注意,我正在使用Python2.6
编辑
结果我把我的问题简化得太简单了,上面的代码很好。但是,如果我将players.py更改为
'''players.py'''
class Player():
"""This class is intended to be subclassed"""
def __init__(self, name):
self.name = name
class Player1(Player):
def __init__(self, name='Homer'):
Player.__init__(self, name)
class Player2(Player):
def __init__(self, name='Barney'):
Player.__init__(self, name)
class Player3(Player):
def __init__(self, name='Moe'):
Player.__init__(self, name)并将main.py中的第5行更改为
ai_players = inspect.getmembers(players,
lambda x: inspect.isclass(x) and issubclass(x, players.Player))我遇到了描述的问题。而且,这也不起作用(当我在repl上测试它时,它也起了作用)
ai_player1 = ai_players[0]()它似乎与继承和默认参数有关。如果我将基类Player更改为
class Player():
"""This class is intended to be subclassed"""
def __init__(self, name='Maggie'):
self.name = name那我就不明白错误了,但球员的名字总是“玛吉”。
EDIT2:
我玩了一会儿,结果是getmembers函数以某种方式“吃掉”了默认参数。从repl上看一下这个日志:
>>> import players
>>> import inspect
>>> ai_players = inspect.getmembers(players,
... lambda x: inspect.isclass(x) and issubclass(x, players.Player))
>>> ai_players = [x[1] for x in ai_players]
>>> ai_players[0].__init__.func_defaults
>>> print ai_players[0].__init__.func_defaults
None
>>> players.Player1.__init__.func_defaults
('Homer',)您知道有什么替代检查模块中成员的方法吗?
EDIT3:
注意,如果给定同一个类两次,issubclass()返回True。(色氨酸)
那是邪恶的人
发布于 2010-07-28 13:48:03
我运行了你的测试代码,对我来说很好。
此错误指示您没有在所有类上实际设置默认的"name“参数。
我会再查一遍。
编辑:
注意,如果给同一个类两次,issubclass()将返回True。
>>> class Foo: pass
>>> issubclass(Foo, Foo)
True因此,您的代码尝试实例化没有名称参数的Player,然后死掉。
好像你把事情搞得太复杂了。我建议更详细地解释您的程序,也许是在另一个问题中,以便获得一些反馈,说明这种方法是否有必要(可能没有)。
发布于 2010-07-28 11:19:53
ai_players = inspect.getmembers(players, inspect.isclass())这一行尝试调用不带参数的inspect.isclass,并给出调用getmembers的结果作为第二个参数。您希望传递函数inspect.isclass,所以只需这样做(编辑:为了更清楚,您需要inspect.getmembers(players, inspect.isclass))。你认为这些圆括号是干什么的?
发布于 2010-07-28 11:23:09
下面是做你想做的事情的更好的方法。
player.py:
class Player:
def __init__(self, name):
self.name = namemain.py:
import player
names = ['Homer', 'Barney', 'Moe']
players = [player.Player(name) for name in names]请注意,您希望定义一个类来保存播放机的详细信息,然后可以根据需要创建该类的尽可能多的实例。
https://stackoverflow.com/questions/3352258
复制相似问题