Skip to content

Instantly share code, notes, and snippets.

@eatonphil
Last active August 29, 2015 14:17
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save eatonphil/4fc6d081f53eedb9a4c4 to your computer and use it in GitHub Desktop.
Save eatonphil/4fc6d081f53eedb9a4c4 to your computer and use it in GitHub Desktop.
Javascript-Style Objects in Python
# 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
@afrepues
Copy link

Just define __call__ and it will be even better ;)

@emidln
Copy link

emidln commented Mar 16, 2015

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

@d1ffuz0r
Copy link

Why do we even use functions?

@donspaulding
Copy link

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!

@alcides
Copy link

alcides commented Mar 16, 2015

Accessing the dictionary via methods can be done.

http://www.goodcode.io/blog/python-dict-object/

@shvechikov
Copy link

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'

@Syerram
Copy link

Syerram commented Mar 16, 2015

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

@cessor
Copy link

cessor commented Mar 17, 2015

So much for "There should be one-- and preferably only one --obvious way to do it."...

@JoePython1
Copy link

Functions in python are actually objects.

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