Separating Data and Logic Using Metaclasses

PyYYC Meetup - 26 July 2016

Franklin Koch

Version 0: The Basics

In [ ]:
from pyyyc_v00 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
this_pres.summarize()
In [ ]:
this_pres.time_per_slide()
In [ ]:
this_pres.strains_eyes()
In [ ]:
js_pres = PyYYCPresentation('JAVASCRIPT', 'RULES', 'PYTHON', 'DROOLS', 'LOLOL')
In [ ]:
js_pres.summarize()
In [ ]:
js_pres.time_per_slide()
In [ ]:
js_pres.strains_eyes()
In [ ]:
print(PyYYCPresentation.__doc__)
In [ ]:
next_pres = PyYYCPresentation('Rowan and Franklin', 'Shoulder bags', '4:30', 10, 'white')
In [ ]:
next_pres.summarize()
In [ ]:
next_pres.time_per_slide()
In [ ]:
next_pres.strains_eyes()

Version 1: A bit of validation logic

In [ ]:
from pyyyc_v01 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
this_pres.set_nslides(15)
In [ ]:
this_pres.nslides
In [ ]:
this_pres.set_time_limit('whatever')
In [ ]:
this_pres.time_limit = 'whatever'
In [ ]:
this_pres.set_slide_color('red')
In [ ]:
this_pres.slide_color
In [ ]:
js_pres = PyYYCPresentation('JAVASCRIPT', 'RULES', 'PYTHON', 'DROOLS', 'LOLOL')

Version 2: Getting a bit more pythonic - Properties wrappers

In [ ]:
from pyyyc_v02 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
this_pres.nslides = 15
In [ ]:
this_pres.nslides
In [ ]:
this_pres._nslides
In [ ]:
this_pres.time_limit = 'whatever'
In [ ]:
this_pres.slide_color = 'red'
In [ ]:
this_pres.slide_color

Version 3: Separating logic with class inheritance

In [ ]:
from pyyyc_v03 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
js_pres = YYCjsPresentation(
    presenter='Franklin',
    topic='How javascript rules and literally everything else drools. lolol',
    time_limit=5.,
    nslides=100,
    slide_color='green'
)
In [ ]:
happy_pres = FreeSpiritPresentation(
    presenter='Moonflower',
    favorite_color=[255, 51, 153]
)
In [ ]:
happy_pres.summarize()

Version 4: More subclassing...

In [ ]:
from pyyyc_v04 import *

Version 5: Extracting more logic out of our classes

In [ ]:
from pyyyc_v05 import *
In [ ]:
confirmColor('red')
In [ ]:
confirmColor([10000, .1, .3])

Version 6: Brief foray into wrappers

In [ ]:
from pyyyc_v06 import *

Version 7: Can we remove more of the repetitive code...?

In [ ]:
from pyyyc_v07 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
this_pres.slide_color = 'red'
In [ ]:
this_pres.slide_color
In [ ]:
this_pres._slide_color

Version 8: Git rid of old subclass structure

In [ ]:
from pyyyc_v08 import *

Version 9: Refactor clunky __init__ function

In [ ]:
from pyyyc_v09 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
new_pres = PyYYCPresentation()
In [ ]:
new_pres.time_limit = '1:30'
In [ ]:
new_pres.time_limit = 90.
In [ ]:
new_pres.summarize()
In [ ]:
new_pres.summarize = 'Oops, but that is just python...'
In [ ]:
summarized_pres = PyYYCPresentation(
    summarize = 'Hmm, that is a bigger oops...'
)
In [ ]:
nefarious_pres = PyYYCPresentation(
    presenter = 'Franklin',
    _presenter = 'Dr. Nefarious'
)

Version 10: Remove the __init__ logic away from your data entirely

In [ ]:
from pyyyc_v10 import *

Version 11: Metaclasses. Finally.

In [ ]:
from pyyyc_v11 import *

Version 12: Introspection with metaclasses

In [ ]:
from pyyyc_v12 import *
In [ ]:
pres = PyYYCPresentation()
In [ ]:
pres.__class__.__name__

In [ ]:
from pyyyc_v12 import *
In [ ]:
pres = PyYYCPresentation()
In [ ]:
pres._props

Version 13: Remove unnecessary redundancy (how's that for a section title?)

In [ ]:
from pyyyc_v13 import *
In [ ]:
this_pres = PyYYCPresentation(
    presenter='Franklin',
    topic='Metaclasses',
    time_limit=90.,
    nslides=10,
    slide_color=[0, 0, 0]
)
In [ ]:
this_pres._slide_color
In [ ]:
this_pres.slide_color = 'red'
In [ ]:
this_pres.slide_color
In [ ]:
this_pres._slide_color

Version 14: Validation on class definition (not instantiation)

In [ ]:
from pyyyc_v14 import *
In [ ]:
class SkateparkAccolades(WithSpecialProps):
    mad_props = StrProp()
    props = StrProp()
    def compliment(self):
        print('Dude, {props}. I mean seriously, {mad_props}!'.format(
            props=self.props,
            mad_props=self.mad_props
        ))

Version 15: Metaclass for auto-documentation

In [ ]:
from pyyyc_v15 import *
In [ ]:
PyYYCPresentation?

Version 16: Automatic class registration

In [ ]:
import pyyyc_v16
In [ ]:
pyyyc_v16._REGISTRY
In [ ]:
for key in pyyyc_v16._REGISTRY:
    print(pyyyc_v16._REGISTRY[key].__doc__ + 60*'_' + '\n')
In [ ]:
 

Version 17: Converting over to properties

In [ ]:
from pyyyc_v17 import *

Version 18: Taking properties and running with it

In [ ]:
from pyyyc_v18 import *
In [ ]:
me = Person(name='Franklin', bio='python, 3ptscience, coffee')
In [ ]:
slide1 = Slide(topic='PyYYC', slide_color='black')
slide2 = Slide(topic='Wrappers', slide_color=[100, 100, 100])
slide3 = Slide(topic='Metaclasses', slide_color='mediumslateblue')
In [ ]:
ppt = PyYYCPresentation(
    presenter=me,
    topic='Data and Logic',
    time_limit=90.,
    slides=[slide1, slide2, slide3]
)
In [ ]:
ppt.cliff_notes()

Learn More:

Visit our website, 3ptscience.com


Use properties yourself!

pip install properties (or find it on Github, Docs, PyPI)


Check out Steno3D, our online 3D visualization software: steno3d.com

pip install steno3d (or find it on Github, Docs, PyPI)


Some good videos: Metaprogramming, Declarative interfaces, or just google python descriptors, wrappers, metaclasses...