Python 反射与可调用对象

3 投票
4 回答
1361 浏览
提问于 2025-04-16 06:36

我有一个两个部分的问题。

>>> class One(object):
...     pass
... 
>>> class Two(object):
...     pass
... 
>>> def digest(constr):
...     c = apply(constr)
...     print c.__class__.__name__
...     print constr.__class__.__name__
... 
>>> digest(Two)
Two
type

怎么才能创建一个名为'Two'的对象呢?使用构造函数(constr())或者c()都不行;而且好像apply会把它变成一种类型。

当你把一个类而不是一个实例传递给一个方法时,会发生什么呢?

4 个回答

1

再举一个例子:

def InstanceFactory(classname):
   cls = globals()[classname]
   return cls() 

class A(object):
   def start(self):
       print "a.start"

class B(object):
   def start(self):
        print "b.start"

InstanceFactory("A").start()
InstanceFactory("B").start()

如果这个类属于另一个模块:

def InstanceFactory(modulename, classname):
    if '.' in modulename:
        raise ValueError, "can't handle dotted modules yet"
    mod = __import__(modulename)
    cls = getattr(mod, classname]
    return cls() 
5

类是高级的对象,所以你可以像这样简单地传递它们:

def createMyClass ( myClass ):
    obj = myClass()
    return obj

class A ( object ):
    pass

>>> x = createMyClass( A )
>>> type( x )
<class '__main__.A'>
1

怎么创建一个叫'Two'的对象呢?使用构造函数(constr())或者c()都不行;而且看起来apply会把它变成一个类型。

上面的评论是针对这段代码说的:

>>> def digest(constr):
...     c = apply(constr)
...     print c.__class__.__name__
...     print constr.__class__.__name__

apply(已弃用:见@pyfunc的回答)确实不会把类Two变成一个类型:它本来就是一个类型。

>>> class Two(object): pass
... 
>>> type(Two)
<type 'type'>

类是第一类对象:它们是type的实例。如果你看下面的例子,就会明白这一点。

>>> two = Two()
>>> type(two)
<class '__main__.Two'>

你可以很清楚地看到,类作为一种类型是可以被type返回的。这里还有另一个例子。

>>> Three = type('Three', (Two, ), {'foo': 'bar'})
>>> type(Three)
<type 'type'>
>>> three = Three()
>>> type(three)
<class '__main__.Three'>

你可以看到type是一个可以被实例化的类。它的构造函数需要三个参数:类的名称、一个基类的元组和一个包含类属性的字典。它会返回一个新的type,也就是一个类。

至于你最后的问题,

如果把一个类而不是一个实例传给一个方法,会发生什么呢?

你需要更具体一点。类本身就是type的实例,所以它们也是第一类对象。问如果把一个类传给一个方法会发生什么,就像问如果把一个整数传给一个方法会发生什么:这完全取决于这个方法的期望是什么。

撰写回答