Skip to content

Instantly share code, notes, and snippets.

@DmitrySoshnikov
Last active January 30, 2016 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DmitrySoshnikov/7fcc5b6acb2eefc345aa to your computer and use it in GitHub Desktop.
Save DmitrySoshnikov/7fcc5b6acb2eefc345aa to your computer and use it in GitHub Desktop.
Delegation-based prototypes: implementing JavaScript semantics in Python
###
# Explicit delegation-based prototypes implementation.
#
# Implementing JavaScript semantics.
#
# Here we show that "delegation" is just a mechanism (a pattern) for
# implementation of the "inheritance" concept. In this specific case we
# have direct inheritance from objects, skipping the "class" step.
#
# See "OO Relationships" article for some details:
# https://medium.com/@DmitrySoshnikov/oo-relationships-5020163ab162
#
# Note: Python itself is already delegation-based ;)
#
# by Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
# MIT Style License
##
# Because JS :P
undefined = None
# To bind a method at resolution
from functools import partial
class JSObject(object):
def __init__(self, props = None):
self.__props = props or {}
# Implement dynamic dispatch
def __getattr__(self, prop):
resolved = self.__props.get(prop)
# Resolved own prop.
if not resolved is None:
# In case if we resolved a function, bind
# it to needed context, making it a method.
if hasattr(resolved, '__call__'):
resolved = partial(resolved, self)
return resolved
# Else, lookup in the prototype chain via delegation.
__proto__ = self.__props.get('__proto__')
# Reached base inheritance link
if __proto__ is None:
return undefined
# Continue lookup.
return __proto__.__getattr__(prop)
foo = JSObject({'x': 10, 'getX': lambda self: self.x})
bar = JSObject({'y': 20, '__proto__': foo})
print(bar.x) # 10, inherited
print(bar.y) # 20, own
print(bar.getX()) # whoo-hoo! methods work too!, 10
##
## Homework exercise: implement `set` and `delete` operations.
##
@kevinastone
Copy link

def __init__(self, props = None):
    self.__props = props or {}

I'd just use kwargs:

def __init__(self, **props):
    self.__props = props

@DmitrySoshnikov
Copy link
Author

@kevinastone, yep, kwargs is a good idea 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment