Last active
August 29, 2015 14:17
-
-
Save eatonphil/4fc6d081f53eedb9a4c4 to your computer and use it in GitHub Desktop.
Javascript-Style Objects in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# After spending too much time away from Python on Javascript, I gave this a shot. To my surprise, it worked! | |
# Since Python doesn't bind "self" implicitly in classes, this looks pretty similar to Python classes. | |
# You want inheritance? Pass in the Parent "class" and copy the key/vals a la Javascript. | |
# Even adding dot syntax is not too tough. | |
def Cat(legs, colorId, name): | |
def sayHi(): | |
print 'Hi, my name is %s. I have %s legs and am %s.' % (this['name'], this['legs'], this['color']) | |
this = { | |
'legs': legs, | |
'color': ['black', 'brown'][colorId], | |
'name': name, | |
'sayHi': sayHi | |
} | |
return this | |
myCat = Cat(4, 0, 'Joey') | |
hisCat = Cat(3, 1, 'Bill') | |
myCat['sayHi']() # Joey | |
hisCat['sayHi']() # Bill |
Why bother with an object at all? functools.partial
has your back:
def say_hi_fn(colors, legs, colorId, name):
print 'Hi, my name is %s. I have %s legs and am %s.' % (name, legs, colors[colorId])
from functools import partial
say_hi = partial(say_hi_fn, ['black', 'brown'])
myCatSpeaks = partial(say_hi, 4, 0, 'Joey')
hisCatSpeaks = partial(say_hi, 3, 1, 'Bill')
myCatSpeaks() # Joey
hisCatSpeaks() # Bill
Why do we even use functions?
I don't recommend the pattern you're trying to mimic here, but if you're going to do it, you could at least implement the attribute access... ;-)
class Object(dict):
def __getattr__(self, name):
if name in self:
return self[name]
Then later...
this = Object({
'legs': legs,
'color': ['black', 'brown'][colorId],
'name': name,
'sayHi': sayHi
})
And finally...
myCat.sayHi()
Also, get your non-PEP8 camelCase off my lawn!
Accessing the dictionary via methods can be done.
You can just return locals()
instead of defining this
explicitly.
def Cat(name):
def say_hi():
print('Hi, %s' % name)
return locals()
>>> Cat('Tom')['say_hi']()
Hi, Tom
>>> Cat('Garfield')['name']
'Garfield'
Once step further. instead of dict key lookup, return a class that takes dictionary and overrides __getitem__
so you can do myCat.sayHi()
def JSDict(dict):
def __init__(self, *args):
dict.__init__(self, args)
def __getattr__(self, key):
if key in self:
return self[key]
else:
return dict.__getitem__(self, key)
def Cat(legs, colorId, name):
def sayHi():
print 'Hi, my name is %s. I have %s legs and am %s.' % (this['name'], this['legs'], this['color'])
this = JSDict({
'legs': legs,
'color': ['black', 'brown'][colorId],
'name': name,
'sayHi': sayHi
})
return this
myCat = Cat(4, 0, 'Joey')
hisCat = Cat(3, 1, 'Bill')
myCat.sayHi() # Joey
hisCat.sayHi() # Bill
So much for "There should be one-- and preferably only one --obvious way to do it."...
Functions in python are actually objects.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just define
__call__
and it will be even better ;)