Setting a class metaclass using a decorator

Following this answer , it seems that the class metaclass can be changed after the class has been defined using the following *:

class MyMetaClass(type):
    # Metaclass magic...

class A(object):
    pass

A = MyMetaClass(A.__name__, A.__bases__, dict(A.__dict__))

Function Definition

def metaclass_wrapper(cls):
    return MyMetaClass(cls.__name__, cls.__bases__, dict(cls.__dict__))

allows me to apply a decorator to a class definition like

@metaclass_wrapper
class B(object):
    pass

It seems that the metaclass mask applies to B, but Bdoes not have an attribute __metaclass__. Is the above method a reasonable way to apply metaclasses to class definitions, although I am defining and redefining a class, or would I be better off just writing

class B(object):
    __metaclass__ = MyMetaClass
    pass

I assume that there are some differences between the two methods.


* Note that the original answer in the related question MyMetaClass(A.__name__, A.__bases__, A.__dict__)returns a TypeError:

TypeError: type() 3 dict, dict_proxy

, __dict__ A ( ) dict_proxy, __dict__ A dict. ? Python 2.x 3.x?

+5
3

__metaclass__... !

__metaclass__, . __metaclass__ . , , __metaclass__ Python , __metaclass__.

, - type, , __metaclass__ , __metaclass__ ( ).


. , ( ), - , , 3 (name, bases, attributes) , 3 , 3 !

Python 2.x:

class A(object):
    __metaclass__ = MyMeta
    def __init__(self):
        pass

, :

attrs = {}
attrs['__metaclass__'] = MyMeta
def __init__(self):
    pass
attrs['__init__'] = __init__
A = attrs.get('__metaclass__', type)('A', (object,), attrs)

, , , , type attrs __metaclass__, , type. , , "" __metaclass__ . , , , __metaclass__ , , .

, - , (, , , !), . , __metaclass__.

__dict__, , ; . , - , , __dict__ () , __dict__ ( btw, ). __dict__ - "dictproxy", , dict, dict. type ; , "" ( , ). 2.x vs 3.x ; Python 3 , dictproxy. Python 2.4 ( 2.x, ) dictproxy __dict__.

+1

, . , , .

. . , , , (obj = dec(obj)), __metaclass__ . .

, , . , ( ), . , , .

, . , __wrapped__, . functools.wraps Python 3 . . , __metaclass__, .

def metaclass(meta):
    def metaclass_wrapper(cls):
        __name = str(cls.__name__)
        __bases = tuple(cls.__bases__)
        __dict = dict(cls.__dict__)

        for each_slot in __dict.get("__slots__", tuple()):
            __dict.pop(each_slot, None)

        __dict["__metaclass__"] = meta

        __dict["__wrapped__"] = cls

        return(meta(__name, __bases, __dict))
    return(metaclass_wrapper)

.

class MetaStaticVariablePassed(type):
    def __new__(meta, name, bases, dct):
        dct["passed"] = True

        return(super(MetaStaticVariablePassed, meta).__new__(meta, name, bases, dct))

@metaclass(MetaStaticVariablePassed)
class Test(object):
    pass

...

|1> Test.passed
|.> True

, ...

class Test(object):
    pass

Test = metaclass_wrapper(Test)

... , , .

|1> Test.passed
|.> True
+3

My summary of your question: “I tried a new, complicated way to do something, and it didn’t quite work. Should I use a simple way instead?”

Yes, you have to do it in a simple way. You did not say why you are interested in inventing a new way to do this.

+1
source

All Articles