Phil Hassey - game dev blog
Phil Hassey as Wolverine
"What kind of
arrogant jerk
has a website like this?"

meta-methods: python vs tinypy

Man, could I have even thought of a title that sounds dustier? It just screams “Get ready for the boring lecture of the year folks.” I should totally re-name this post to something like “putting your brain through a blender .. FOR FUN!” Or maybe I should have gone the pretentious route and named it something like “Analysis of modern programming meta-method paradigms.” Actually, that sounds even dustier than my original title. At least my original one falsely implies that there is some competition going on in this post by my use of the “vs”.

Here’s how python does it:

class X:
    def __get__(self,k): return “OK”

Here’s how tinypy does it:

class MetaX:
    def __get__(self,k): return “OK”
class X:
    def __init__(self): setmeta(self,MetaX)

Okay .. so .. the python way is WAY more readable. Nice 🙂 So let me remember if there was a good reason for doing it a different way in tinypy … I think the answer is “maybe” ? Here’s what I can come up with:

  • In tinypy dict == object, which means a.x == a[‘x’]. (I’m not sure how that’s relevant, but it does mean that I have no need for a __getattr__.)
  • lua does it that way! (I have copied many other lua design decisions, so why not copy another!)
  • It’s faster? (In a sort of, if only tinypy were as fast as python is to begin with kind of way.)
  • It was easier to hack together in an afternoon! (Well, actually .. looking at the python code, I think the python way might have been easier.)

So what did I gain by going the lua route instead of the python route? I’m not entirely sure .. but it sure seemed like a good idea at the time.

A few days later …

With a bit of effort, I’ve come up with a few more reasons why I did this in tinypy:

  • Not only are dicts objects but they can also be classes. This is done by having a __call__ meta, so if you have class X: .. X() calls getmeta(X).__call__. This is relevant because if the class itself had a __call__ method, how would you define your class so that it knows to create your object with a __call__ method? (Probably by having a __new__ method that isn’t copied to the object.)
  • The one way the previous point is relevant, is that the object __new__ would probably have to be smarter than how I create objects currently. It would have to realize that __new__ methods don’t get copied into objects.
  • Also, I would probably have to internally track what is a class vs what is an object. So I know when I do something like X.test(self) .. and my class X has the unbound method of __get__, it knows not to try any meta magic.

Okay .. those aren’t great reasons. The nice thing about tinypy being .. tinypy .. is that if this continues to bother me for the rest of the day, I can probably try out the implementation in a couple hours. If you want to see the current meta implementation, it’s in subversion.

Anyone care to comment on the whole lua vs python style meta-methods stuff? I’m pretty sure I’m not sure at all what I think about them!

One Response to “meta-methods: python vs tinypy”

  1. Chris Swetenham Says:

    Although it is very elegant, a.x == a[“x”] is actually one of the design decisions I like least in Lua, because it means that you can’t have methods on an arbitrary indexable collection.

    Metamethods also have a problem in Lua; they must be directly in the metatable of an object (__add for instance won’t be looked up in the metatable.__index of the metatable, etc, but only in the metatable itself). You can either give instances a metatable whose __index is their class, or put the metamethods in the class and have the class as metatable, but either way there’s no simple solution to inheriting metamethods in Lua.