开发者

python metaclasses at module level

I read What is a metaclass in Python?

and I tried to replicate the upper metaclass from the example and found that this doesn't work in all cases:

def upper(cls_name, cls_parents, cls_attr):                                     
    """ Make all class attributes uppper case """                               
    attrs = ((name, value) for name, value in cls_attr.items()                  
            if not name.startswith('__'))                                       
    upper_开发者_StackOverflow社区atts = dict((name.upper(), value) for name, value in attrs)           
    return type(cls_name, cls_parents, upper_atts)                              

__metaclass__ = upper #Module level
class Foo:                                                                      
    bar = 1                                                                     
f =  Foo()
print(f.BAR) #works in python2.6

The above fails (with an attribute error) in python3 which I think is natural because all classes in python3 already have object as their parent and metaclass resolution goes into the object class.

The question:

How do I make a module level metaclass in python3?


The module level metaclass isn't really "module level", it has to do with how class initialization worked. The class creation would look for the variable "__metaclass__" when creating the class, and if it wasn't in the local environment it would look in the global. Hence, if you had a "module level" __metaclass__ that would be used for every class afterwards, unless they had explicit metaclasses.

In Python 3, you instead specify the metaclass with a metaclass= in the class definition. Hence there is no module level metaclasses.

So what do you do? Easy: You specify it explicitly for each class.

It's really not much extra work, and you can even do it with a nice regexp search and replace if you really have hundreds of classes and don't want to do it manually.


If you want to change all the attributes to upper case, you should probably use the __init__ method to do so, than use a metaclass.

Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).

-- Python Guru Tim Peters

If you need something deeper, you should also evaluate using Class Decorators.

Using MetaClasses and understanding how the classes are created is so unnecessary as long as you want to do something that you can do using class decorators or initialization.

That said, if you really want to use a Metaclass tho' pass that as a keyword argument to the class.

class Foo(object, metaclass=UpperCaseMetaClass)

where UpperCaseMetaClass is a class that extends type and not a method.

class UpperCaseMetaClass(type):
    def __new__():
        #Do your Magic here.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜