Steven D'Aprano wrote:
To answer your direct question, all you need to do is manually imitate what
Python does when you call a descriptor (see below):


py> MyClass.method_list[0].__get__(MyClass, None)()
Hello World


So, inside the foo() method, do this:

    @classmethod
    def foo(cls):
        cls.method_list[0].__get__(cls, None)()


and it should work.

"What the hell is a descriptor?" I hear you ask. Don't worry about them,
they are an advanced part of Python, used to implement methods (regular,
class and static) and properties. If you care, you can read this:

http://docs.python.org/2/howto/descriptor.html

but you may find it heavy going. (I know I did the first five times I
read it.)

Here's another solution: use a regular function object instead of a
method. This relies on an unusual, but deliberate, quirk of the way Python
implements methods: they are actually regular functions inside the class
body when the class is created, and don't get turned into methods until you
do a lookup like "self.spam" or "cls.ham".


class MyClass(object):
    @classmethod
    def foo(cls):
        # Note that you manually provide the class argument.
        cls.method_list[0](cls)

    def bar(cls):
        print("Hello World")

    # At this time, bar is still a regular function object, not a
    # method of any sort.
    method_list = [bar]
    del bar  # just to avoid any confusion


By *not* turning bar into a class method, it remains an ordinary
function object. You then store the function object inside the list,
and when you access it via method_list[0] Python gives you the regular
function, not a method. Since it is a regular function, it is callable,
but you have to manually provide the cls argument.


Thank you for this great answer!
I like the first approach (using __get__()). I tried it out but got problem when bar operates on a class variable of MyClass:

class MyClass(object):

    x = "Hello World"

    @classmethod
    def foo(cls):
        cls.method_list[0].__get__(cls, None)()

    @classmethod
    def bar(cls):
        print(cls.x)

    method_list = [bar]


I get:
File "test.py", line 17, in bar
    print(cls.x)
AttributeError: type object 'type' has no attribute 'x'

When using Peter Otten's solution bar is able to access cls.x.


_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to