Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with this simple python metaclass?

Digression Start

I just learnt what metaclasses are in Python. I don't think that the creators of python wanted everyone to use them. I mean name something a metaclass which might not be a class in most cases is enough to divert most people away from this concept!

Digression end

On to my question. I wrote this simple metaclass to add a default doc string to all classes that are created in the module. But it is not working:

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__

Output:

None
None

What am I doing wrong?

like image 835
ritratt Avatar asked Jun 29 '12 04:06

ritratt


3 Answers

I'm not entirely familiar with the global approach you are doing, setting __metaclass__ like that. For all I know, its another valid style.

But I will provide an example of what I am familiar with:

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
like image 158
jdi Avatar answered Oct 12 '22 12:10

jdi


I made your example work:

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. Make the "meta class" used.
  2. Correct the signature of the "class creation function". The cls will be created by us.
  3. Have an "old" and a "new" docstring in order to distinguish.
like image 42
glglgl Avatar answered Oct 12 '22 13:10

glglgl


See this answer: Python metaclass and the object base class

Providing the object base class overrides the module-level metaclass and replaces it with type (the metaclass of object).

In addition, your metaclass is faulty and won't work even if you get it to apply (by setting __metaclass__ inside the class). It should only accept three arguments. You usually see examples that accept four, but that's because the metaclass is usually, guess what, a class, so it accepts an extra "self" argument (which by convention is called cls for metaclasses).

like image 20
BrenBarn Avatar answered Oct 12 '22 13:10

BrenBarn