Question

So if I have a class with method foo:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def foo(self):
        return "Hey I am called %s." % self.name

and I decide to make a wrapper:

def bar(obj, func):
    def inner(*args, **kwargs):
        print "I am %d years old." % obj.age
        return func(*args, **Kwargs)
    return inner

And later on I just go ahead and replace obj.foo on an instance of the A class, all's well.

Stick = A('Stick', 32)
Stick.foo = bar(Stick, Stick.foo)
Stick.foo()
>>> I am 32 years old.
>>> Hey I am called Stick.

So that's fine, but if I omit the return func(*args, **kwargs) bit, it acts as though it just replaces the method in the same way as one might expect when using types.MethodType to replace an instance method on the fly.

def bar(obj):
    def inner(*args, **kwargs):
        return "I am %d years old." % obj.age
    return inner
Stick.foo = bar(Stick)
Stick.foo()
>>> I am 32 years old.

So perhaps there is some kind of overhead incurred in this way, or some other deficit to this way of implementing a strategy pattern, but... this seems to work out pretty well. Compared to bringing in types.MethodType for the purpose of writing functions that have the word self in them, it is unclear to me as to why importing types.MethodType would be preferred to simply using wrappers that don't return the original method, or by using the assignment syntax instead of the @decorator way of doing things.

I feel I often see the suggestion of using the types library where someone seems to want something like a strategy pattern - not always, but often enough to where it appears that many users may be overlooking something which Python seems to already be equipped to handle. As in this speech from PyCon 2009 where clear examples are given that urge the coder to 'look to the language first' for features which may already exist before asking for changes -- I believe the arc of his speech is more aimed at over-coding or going out and writing a PEP, but I think it applies here too -- should one turn to a library when a wrapper is all they needed?

So unless there is something that makes the types approach more compelling, in which case the answer is obvious, here's what I'm asking: In which situation(s) is it preferred to use types.MethodType as opposed to simply writing wrappers like those I've demonstrated?

Was it helpful?

Solution

It's a fairly rare occurrence that you'd need or want to use anything in the types module, though I will admit to having subclassed types.ModuleType in the past for flexmock. The primary purpose of this module is mainly to give you names for classes that would otherwise be awkward to refer to, with the caveat that some of them are also known by things like dict or int.

It is only very rarely that you'd actually need to use these names to construct or subclass something. So what do you do with something like types.MethodType? Use it for introspection.

Say you wanted to write an automatic documentation generator. Maybe you hand your autodoc the module in question. Using types.FunctionType, types.TypeType, and maybe types.ClassType (for old-style classes), you can figure out what things in the module are functions and classes and call appropriate documentation formatters for each. For each class, you can iterate through its members and use types.MethodType to sort out the class's methods from its other attributes and document each as appropriate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top