Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__metaclass__ in Python 3

Tags:

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      def __init__(self, name, alias=None):         self._name = name         self._alias = alias   d = Table d.student__s 

But in Python 3.5 I get an attribute error instead:

Traceback (most recent call last):   File "/Users/wyx/project/python3/sql/dd.py", line 31, in <module>     d.student__s AttributeError: type object 'Table' has no attribute 'student__s' 
like image 463
wyx Avatar asked Aug 18 '16 08:08

wyx


People also ask

What is the use of metaclass in Python?

A metaclass in Python is a class of a class that defines how a class behaves. A class is itself an instance of a metaclass. A class in Python defines how the instance of the class will behave. In order to understand metaclasses well, one needs to have prior experience working with Python classes.

What is __ bases __ in Python?

Python provides a __bases__ attribute on each class that can be used to obtain a list of classes the given class inherits. The __bases__ property of the class contains a list of all the base classes that the given class inherits.

How do you sets the metaclass of class A to B in Python?

In order to set metaclass of a class, we use the __metaclass__ attribute. Metaclasses are used at the time the class is defined, so setting it explicitly after the class definition has no effect. The best idea I can think of is to re-define whole class and add the __metaclass__ attribute dynamically somehow.

Is type a metaclass Python?

type is a metaclass, of which classes are instances. Just as an ordinary object is an instance of a class, any new-style class in Python, and thus any class in Python 3, is an instance of the type metaclass.


1 Answers

Python 3 changed how you specify a metaclass, __metaclass__ is no longer checked.

Use metaclass=... in the class signature:

class Table(object, metaclass=MetaTable): 

Demo:

>>> 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): ...     def __init__(self, name, alias=None): ...         self._name = name ...         self._alias = alias ... >>> d = Table >>> d.student__s <__main__.Table object at 0x10d7b56a0> 

If you need to provide support for both Python 2 and 3 in your codebase, you can use the six.with_metaclass() baseclass generator or the @six.add_metaclass() class decorator to specify the metaclass.

like image 155
Martijn Pieters Avatar answered Oct 12 '22 08:10

Martijn Pieters