SlideShare a Scribd company logo
1 of 50
Download to read offline
Induction in metaclasses
Induction in metaclasses
ME
TA CL
ASS
Ionel Cristian Mărieș — Python / OSS enthusiast
blog.ionelmc.ro
github.com/ionelmc
Why?
Lots of unwarranted fear ... ʺitʹs magicʺ, ʺthey are badʺ etc
They present lots of interesting opportunities for:
Reducing boilerplate.
Nicer APIs
Especially useful in designs that rely on subclassing (subclasses will use the same
metaclass).
They have a tax:
Introspection issues, unhappy linters.
Need to understand them to use effectively. Because some interactions are not explicit.
Few basic things
Objects allow overriding certain object interfaces and operations
Like the function call operator:
>>> class Funky:
...     def __call__(self):
...         print("Look at me, I work like a function!")
>>> f = Funky()
>>> f()
Look at me, I work like a function!
Or a ribute access:
>>> class MagicHat:
...     def __getattr__(self, name):
...         return "Imagine a %a ..." % name
>>> hat = MagicHat()
>>> hat.rabbit
"Imagine a 'rabbit' ..."
But there are some caveats
Magic methods are looked up (resolved) on the class, not on the instance. [1]
>>> class Simple:
...     pass
>>> s = Simple()
Doesnʹt work:
>>> s.__call__ = lambda self: "x"
>>> s()
Traceback (most recent call last):
  ...
TypeError: 'Simple' object is not callable
Aha! It is resolved on the class:
>>> Simple.__call__ = lambda self: "x"
>>> s()
'x'
[1] Exceptions: Python 2 old‑style objects and few special‑cased methods.
Constructors and initialisers
Instance creation is just a magic method you can override:
>>> class WithConstructor(object):
...     def __new__(cls, value):
...         print("Creating the instance")
...         return super().__new__(cls)
...
...     def __init__(self, value):
...         print("Initialising the instance")
...         self.value = value
>>> WithConstructor(1)
Creating the instance
Initialising the instance
<__main__.WithConstructor object at 0x...>
Note that if  __new__  returns a different type of object then a different 
__init__  would be called (from the other typeʹs class).
Types and instances
A class is just an instance of something else, a metaclass.
You can have a custom metaclass
So, if a class is just an instance, we can customise the creation process:
>>> class Meta(type):
...     pass
>>> class Complex(metaclass=Meta):
...     pass
>>> Complex()
<__main__.Complex object at 0x...>
Normally, the metaclass should be a subclass of  type . More on this later.
The instantiation dance in detail
Remember that:
__init__  does not create instances,  __new__  does.
Magic methods are resolved on the metaclass.  Complex()  is equivalent to 
Meta.__call__ .
The full interface
__prepare__(mcs, name, bases, **kwargs)  ‑ New in Python 3, returns the
namespace dictionary
__new__(mcs, name, bases, attrs, **kwargs)  ‑ Returns an instance of
Meta
__init__(cls, name, bases, attrs, **kwargs)  ‑ Runs initialisation code,
typeʹs __init__ doesnʹt do anything
kwargs: only in Python 3, example:
class Class(object, metaclass=Meta, a=1, b=2, c=3):
    pass
__call__  ‑ Returns and instance of Complex (which in turn is instance of Meta).
Because magic methods are resolved on the class.
Syntactic sugar
>>> class Simple(Base):
...     foo = 'bar'
Is equivalent to:
>>> Simple = type('Simple', (Base, ), {'foo': 'bar'})
~
>>> class Simple(Base, metaclass=Meta):
...     foo = 'bar'
Is equivalent to:
>>> Simple = Meta('Simple', (Base, ), {'foo': 'bar'})
Going back to the type of the metaclass
Normally you inherit from type because it implements all the necessary interface
for a well functioning class.
But you can use just as well a plain callable.
And let horrible stuff like this happen:
>>> class NotAnymore(metaclass=print):
...     pass
NotAnymore () {'__qualname__': 'NotAnymore', '__module__': '__main__'}
>>> repr(NotAnymore)
'None'
Why can the metaclass be any callable
Why can the metaclass be any callable
Useless tricks
>>> type(type) is type
True
But how about:
>>> class mutable(type):  # dummy type, so the instance has a __dict__
...     pass              # (mutable in other words)
...
>>> class typeish(type, metaclass=mutable):
...     pass
...
>>> typeish.__class__ = typeish
>>> print(type(typeish) is typeish)
True
New in Python 3: __prepare__
Allows users to customize the class creation before the body of the class is
executed.
Basically allows you to return a different object as the namespace (instead of a
dict).
What can you do with it? Lots of interesting stuff:
Single dispatch
Duplicate validators
Field order aware objects
Disallow overrides with __prepare__
>>> class StrictDict(dict):
...     def __setitem__(self, name, value):
...         if name in self:
...             raise RuntimeError('You already defined %r!' % name)
...         super().__setitem__(name, value)
...
>>> class StrictMeta(type):
...     def __prepare__(name, bases):
...         return StrictDict()
...
>>> class Strict(metaclass=StrictMeta):
...     a = 1
...     a = 2  # Ooops. Will ever anyone notice this?
Traceback (most recent call last):
  ...
RuntimeError: You already defined 'a'!
Single dispatch with __prepare__ ﴾1/3﴿
Suppose we have this code:
>>> class Int(int):
...     def __repr__(self):
...         return "Int(%d)" % self
...
...     @dispatching.dispatch
...     def __add__(self, other:int):
...         return Int(int.__add__(self, other))
...
...     @__add__.dispatch
...     def __add__(self, other:str):
...         return Int(int.__add__(self, int(other)))
>>> i = Int(5)
>>> i + 1
Int(6)
>>> i + "2"
Int(7)
Single dispatch with __prepare__ ﴾2/3﴿
We can make it seamless using  __prepare__ :
>>> class Int(int, metaclass=SingleDispatchMeta):
...     def __repr__(self):
...         return "Int(%d)" % self
...
...     def __add__(self, other:int):
...         return Int(int.__add__(self, other))
...
...     def __add__(self, other:str):
...         return Int(int.__add__(self, int(other)))
>>> i = Int(5)
>>> i + 1
Int(6)
>>> i + "2"
Int(7)
Single dispatch with __prepare__ ﴾3/3﴿
>>> import dispatching
>>> class SingleDispatchCollector(dict):
...     def __setitem__(self, name, value):
...         if callable(value):
...             if name in self:
...                 self[name].dispatch(value)
...             else:
...                 super().__setitem__(name,
...                                     dispatching.dispatch(value))
...         else:
...             super().__setitem__(name, value)
>>> class SingleDispatchMeta(type):
...     def __prepare__(name, bases):
...         return SingleDispatchCollector()
What else can you do with metaclasses
Docstring fixers
DSLs, Models
Class or usage validators
Subclass registry systems
All sorts of behavior changing
Warning/deprecation systems
Automatic function decoration
Metaclasses vs class decorators
A class decorator takes a class as input and, hopefully, returns a class.
The decorator usually returns the same class after making some changes to it (eg:
monkey‑patching).
Disadvantages of a decorator:
Lack of flexibility. They are equivalent to a  __init__  method in the
metaclass.
When accessing methods through the class or instance they become bound
functions (which is not the same thing as the original function).
Solution is to pull them out of  __dict__ .
It becomes boilerplate.
Doesnʹt work well with subclassing.
Known uses
Pythonʹs abc
Django
SQLAlchemy
fields
$ pip install fields
>>> from fields import Fields
>>> class Pair(Fields.a.b):
...     pass
...
>>> Pair(1, 2)
Pair(a=1, b=2)
Where do we draw the line?
Metaclasses have some disadvantages. What is a good tradeoff?
Whatʹs worse, boilerplate or implicit behavior?
Two important things to consider:
Is the implicit behavior intuitive?
Does the abstraction leak?
And last ....
Q: What does the metaclass say to the class?
A: Youʹre  __new__  to me.
Induction in metaclasses

More Related Content

Similar to Induction in metaclasses

Real-World Scala Design Patterns
Real-World Scala Design PatternsReal-World Scala Design Patterns
Real-World Scala Design Patterns
NLJUG
 

Similar to Induction in metaclasses (20)

EnScript Workshop
EnScript WorkshopEnScript Workshop
EnScript Workshop
 
San Diego PHP Craft CMS
San Diego PHP Craft CMS San Diego PHP Craft CMS
San Diego PHP Craft CMS
 
About Functional Programming
About Functional ProgrammingAbout Functional Programming
About Functional Programming
 
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Real-World Scala Design Patterns
Real-World Scala Design PatternsReal-World Scala Design Patterns
Real-World Scala Design Patterns
 
Elegant Solutions For Everyday Python Problems - Nina Zakharenko
Elegant Solutions For Everyday Python Problems - Nina ZakharenkoElegant Solutions For Everyday Python Problems - Nina Zakharenko
Elegant Solutions For Everyday Python Problems - Nina Zakharenko
 
The Art of Clean code
The Art of Clean codeThe Art of Clean code
The Art of Clean code
 
Metaprogramming JavaScript
Metaprogramming  JavaScriptMetaprogramming  JavaScript
Metaprogramming JavaScript
 
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScriptLotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
 
Python for dummies
Python for dummiesPython for dummies
Python for dummies
 
From Java to Python: beating the Stockholm syndrome
From Java to Python: beating the Stockholm syndromeFrom Java to Python: beating the Stockholm syndrome
From Java to Python: beating the Stockholm syndrome
 
Zend Framework And Doctrine
Zend Framework And DoctrineZend Framework And Doctrine
Zend Framework And Doctrine
 
Metaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Metaclasses – Python’s Object-Oriented Paradigm and Its MetaprogrammingMetaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
Metaclasses – Python’s Object-Oriented Paradigm and Its Metaprogramming
 
Gdd pydp
Gdd pydpGdd pydp
Gdd pydp
 
Beyond the Style Guides
Beyond the Style GuidesBeyond the Style Guides
Beyond the Style Guides
 
srt311 Project2
srt311 Project2srt311 Project2
srt311 Project2
 
Python internals and how they affect your code - kasra ahmadvand
Python internals and how they affect your code - kasra ahmadvandPython internals and how they affect your code - kasra ahmadvand
Python internals and how they affect your code - kasra ahmadvand
 
Rails 3 hints
Rails 3 hintsRails 3 hints
Rails 3 hints
 
Functional Programming In Jdk8
Functional Programming In Jdk8 Functional Programming In Jdk8
Functional Programming In Jdk8
 

Recently uploaded

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 

Recently uploaded (20)

WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 

Induction in metaclasses