6

题外话开始

我刚刚了解了 Python 中的元类。我不认为 python 的创建者希望每个人都使用它们。我的意思是命名一些在大多数情况下可能不是类的元类足以让大多数人远离这个概念!

题外话结束

关于我的问题。我编写了这个简单的元类来为模块中创建的所有类添加一个默认的文档字符串。但它不起作用:

def metest(cls,name,bases,dict):
    cls.setattr(cls,'__doc__',"""Default Doc""")
    return type(cls,(),{})

__metaclass__=metest

class test(object):
    pass

print test.__doc__

t=test()

print t.__doc__

输出:

None
None

我究竟做错了什么?

4

5 回答 5

4

我不完全熟悉你正在做的全局方法,这样设置__metaclass__。据我所知,它是另一种有效的风格。

但我将提供一个我熟悉的示例:

class MeTest(type):
    def __new__(cls,name,bases,dict):
        dict['__doc__'] = """Default Doc"""
        return type.__new__(cls,name,bases,dict)

class Test(object):
    __metaclass__ = MeTest
于 2012-06-29T05:23:42.653 回答
3

我让你的例子工作:

def metest(name, bases, dict):
    print name, bases, dict
    dict['__doc__'] = """New Doc"""
    cls = type(name+"_meta", bases, dict)
    return cls

class Test(object):
    "Old doc"
    __metaclass__ = metest

print Test
print Test.__doc__

t = Test()

print t.__doc__
  1. 使用“元类”。
  2. 更正“类创建函数”的签名。遗嘱由cls我们创建。
  3. 有一个“旧”和一个“新”文档字符串以便区分。
于 2012-06-29T06:06:29.047 回答
2

请参阅此答案:Python 元类和对象基类

提供object基类会覆盖模块级元类并将其替换为type(的元类object)。

此外,您的元类有问题,即使您应用它(通过__metaclass__在类内设置)也无法工作。它应该只接受三个参数。您通常会看到接受四个的示例,但那是因为元类通常是,你猜怎么着,一个class,所以它接受一个额外的“self”参数(按照惯例cls,元类调用它)。

于 2012-06-29T05:13:05.113 回答
1

可能这就是你想要的。继承 fromobject会生成元类type,所以如果你想使用全局元类,你不能这样做

def metest(name, bases, dct):
    dct['__doc__'] = """Default Doc"""
    return type(name, bases, dct)

__metaclass__=metest

class test:
    pass

print test.__doc__

t=test()

print t.__doc__
于 2012-06-29T07:01:40.853 回答
1

正如上面 BrenBarn 所述,您的模块级元类被覆盖。要解决此问题,请尝试将其编码为返回 cls而不是将其设置为类实例。

于 2016-03-31T07:09:05.570 回答