首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的动态类实例化

Python中的动态类实例化
EN

Stack Overflow用户
提问于 2010-07-28 11:14:04
回答 3查看 3.5K关注 0票数 5

我在一个模块里有很多类。让我们说:

代码语言:javascript
复制
'''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模块。

代码语言:javascript
复制
'''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...]

但是,我得到以下错误

代码语言:javascript
复制
TypeError: __init__() takes exactly 2 arguments (1 given)

有趣的是,当我没有在列表理解或for循环中实例化类对象时,一切都很好。

代码语言:javascript
复制
# this does not throw an error
ai_player1 = ai_players[0]()
print ai_player1
# >> 'Homer'

那么,为什么Python不允许我实例化列表理解/ for循环中的类(我也在for循环中尝试过)?

或者更好的方法:如何动态加载模块中的所有类并在列表中实例化它们?

*注意,我正在使用Python2.6

编辑

结果我把我的问题简化得太简单了,上面的代码很好。但是,如果我将players.py更改为

代码语言:javascript
复制
'''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行更改为

代码语言:javascript
复制
ai_players = inspect.getmembers(players, 
             lambda x: inspect.isclass(x) and issubclass(x, players.Player))

我遇到了描述的问题。而且,这也不起作用(当我在repl上测试它时,它也起了作用)

代码语言:javascript
复制
ai_player1 = ai_players[0]()

它似乎与继承和默认参数有关。如果我将基类Player更改为

代码语言:javascript
复制
class Player():
    """This class is intended to be subclassed"""
    def __init__(self, name='Maggie'):
        self.name = name

那我就不明白错误了,但球员的名字总是“玛吉”。

EDIT2:

我玩了一会儿,结果是getmembers函数以某种方式“吃掉”了默认参数。从repl上看一下这个日志:

代码语言:javascript
复制
>>> 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。(色氨酸)

那是邪恶的人

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-28 13:48:03

我运行了你的测试代码,对我来说很好。

此错误指示您没有在所有类上实际设置默认的"name“参数。

我会再查一遍。

编辑:

注意,如果给同一个类两次,issubclass()将返回True

代码语言:javascript
复制
>>> class Foo: pass
>>> issubclass(Foo, Foo)
True

因此,您的代码尝试实例化没有名称参数的Player,然后死掉。

好像你把事情搞得太复杂了。我建议更详细地解释您的程序,也许是在另一个问题中,以便获得一些反馈,说明这种方法是否有必要(可能没有)。

票数 2
EN

Stack Overflow用户

发布于 2010-07-28 11:19:53

代码语言:javascript
复制
ai_players = inspect.getmembers(players, inspect.isclass())

这一行尝试调用不带参数的inspect.isclass,并给出调用getmembers的结果作为第二个参数。您希望传递函数inspect.isclass,所以只需这样做(编辑:为了更清楚,您需要inspect.getmembers(players, inspect.isclass))。你认为这些圆括号是干什么的?

票数 1
EN

Stack Overflow用户

发布于 2010-07-28 11:23:09

下面是做你想做的事情的更好的方法。

player.py:

代码语言:javascript
复制
class Player:
    def __init__(self, name):
        self.name = name

main.py:

代码语言:javascript
复制
import player

names = ['Homer', 'Barney', 'Moe']
players = [player.Player(name) for name in names]

请注意,您希望定义一个类来保存播放机的详细信息,然后可以根据需要创建该类的尽可能多的实例。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3352258

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档