Shouldn't __metaclass__ force the use of a metaclass in Python?

I've been trying to learn about metaclasses in Python. I get the main idea, but I can't seem to activate the mechanism. As I understand it, you can specify M to be as the metaclass when constructing a class K by setting __metaclass__ to M at the global or class level. To test this out, I wrote the following program:

p = print

class M(type):
    def __init__(*args):
        type.__init__(*args)
        print("The rain in Spain")

p(1)
class ClassMeta:
    __metaclass__ = M

p(2)
__metaclass__ = M
class GlobalMeta: pass

p(3)
M('NotMeta2', (), {})

p(4)

However, when I run it, I get the following output:

C:\Documents and Settings\Daniel Wong\Desktop>python --version
Python 3.0.1

C:\Documents and Settings\Daniel Wong\Desktop>python meta.py
1
2
3
The rain in Spain
4

Shouldn't I see "The rain in Spain" after 1 and 2? What's going on here?


Asked by: Kellan331 | Posted: 06-12-2021






Answer 1

In Python 3 (which you are using) metaclasses are specified by a keyword parameter in the class definition:

class ClassMeta(metaclass=M):
  pass

Specifying a __metaclass__ class property or global variable is old syntax from Python 2.x and not longer supported. See also "What's new in Python 3" and PEP 2115.

Answered by: Owen713 | Posted: 07-01-2022



Answer 2

This works as you expect in Python 2.6 (and earlier), but in 3.0 metaclasses are specified differently:

class ArgMeta(metaclass=M): ...

Answered by: Chelsea460 | Posted: 07-01-2022



Answer 3

The syntax of metaclasses has changed in Python 3.0. The __metaclass__ attribute is no longer special at either the class nor the module level. To do what you're trying to do, you need to specify metaclass as a keyword argument to the class statement:

p = print

class M(type):
    def __init__(*args):
        type.__init__(*args)
        print("The rain in Spain")

p(1)
class ClassMeta(metaclass=M): pass

Yields:

1
The rain in Spain

As you'd expect.

Answered by: David737 | Posted: 07-01-2022



Similar questions

metaclass - __metaclass__ in Python 3

In Python2.7 this code can work very well, __getattr__ in MetaTable will run. But in Python 3 it doesn't work. class MetaTable(type): def __getattr__(cls, key): temp = key.split("__") name = temp[0] alias = None if len(temp) > 1: alias = temp[1] return cls(name, alias) class Table(object): __metaclass__ = MetaTable...


metaclass - __metaclass__ in Python 3

In Python2.7 this code can work very well, __getattr__ in MetaTable will run. But in Python 3 it doesn't work. class MetaTable(type): def __getattr__(cls, key): temp = key.split("__") name = temp[0] alias = None if len(temp) > 1: alias = temp[1] return cls(name, alias) class Table(object): __metaclass__ = MetaTable...


metaclass - python __metaclass__ doesn’t work

class UpperAttrMetaClass(type): def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr): attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return type.__new__(upperattr_metaclass,future_class_name, future_class_parents, uppercase_at...


Python __metaclass__ inheritance issue

My issue is that I am using a metaclass to wrap certain class methods in a timer for logging purposes. For example: class MyMeta(type): @staticmethod def time_method(method): def __wrapper(self, *args, **kwargs): start = time.time() result = method(self, *args, **kwargs) finish = time.time() sys.stdout.write('instancemethod %s took %0...


metaclass - Finding __metaclass__ used before redefinition in Python

I want to redefine a __metaclass__ but I want to fall back to the metaclass which would have been used if I hadn't redefined. class ComponentMetaClass(type): def __new__(cls, name, bases, dct): return <insert_prev_here>.__new__(cls, name, bases, dct) class Component(OtherObjects): __metaclass__ = ComponentMetaClass From what I understand, the __metaclass__ used b...


python - Why can't I change the __metaclass__ attribute of a class?

I have a weird and unusual use case for metaclasses where I'd like to change the __metaclass__ of a base class after it's been defined so that its subclasses will automatically use the new __metaclass__. But that oddly doesn't work: class MetaBase(type): def __new__(cls, name, bases, attrs): attrs["y"] = attrs["x"] + 1 return type.__new__(cls, name, bases, attr...


python - Dynamic Class Variables - locals() vs __metaclass__

To create dynamic class variables you seem to have two options - using locals() or __metaclass__. I am not a fan of assigning to locals() but it seems to work in a class definition and is more succinct than it's __metaclass__ alternative. Is it reliable to use locals() in this way? What are the advantages/drawbacks for either solution?


python - Why __metaclass__ doesn't work?

After reading parts of Django source code, I want to do some test and write codes below to watch how metaclass works: class MyMeta(type): def __new__(cls, name, bases, attrs): print cls, name, bases, attrs return super(MyMeta, cls).__new__(cls, name, bases, attrs) class AttrFiled(object): pass class Test(MyMeta): name = AttrField() It always compl...


class - How does this use of Python's __metaclass__ work?

Here in this IPython Notebook I found a presentation about generators and functional programming. I stumbled upon __metaclass__: Why are Real and float arguments of Accounting? What usually is there now is in bases, but is it required to write Real and...


python - __metaclass__ adding invalid attribute to class created?

metaclass adding invalid attribute to class? Here is my code: def __metaclass__(clsname, bases, dct): dct["key1"] = "value1" dct["invalid identifier"] = "value2" return type(clsname, bases, dct) class Cls(): pass for name in dir(Cls): if not name.startswith("_"): print name when I run it, I got: >>> invali...


Python 2.7 - Is this a valid use of __metaclass__?

Closed. This question needs details or clarity. It ...


metaclass - __metaclass__ in Python 3

In Python2.7 this code can work very well, __getattr__ in MetaTable will run. But in Python 3 it doesn't work. class MetaTable(type): def __getattr__(cls, key): temp = key.split("__") name = temp[0] alias = None if len(temp) > 1: alias = temp[1] return cls(name, alias) class Table(object): __metaclass__ = MetaTable...


linux - Why protobuf generates python class with __metaclass__ attribute?

protobuf generates C++/Java classes, and these are static typed class, enough for encoding/decoding. Why it generates python classes with metaclass attribute: I would suppose ordinary class will be enough to do rpc, like C++/Java generated classes. Why python should use dynamic class? Thanks.






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top