Lapin-Blanc
Lapin-Blanc

Reputation: 1985

Dynamic function creation in Metaclass

I'm doing my first steps in Python 2.7 Metaprogramming, and wrote following code :

class MetaClass(type):
    def __init__(cls, name, bases, attrs):
        print "Defining class : %s" % (cls,)
        ra = [(key, value) for key, value in cls.__dict__.items() if not key.startswith('_')]
        for (k, v) in ra:
            setattr(cls, "_"+k, v)
            def get_a(cls):
                print "Getting value of " + k
            get_a(cls)
            get_a.__name__ = "get_" + k
            get_a.__doc__ = "Documentation for get_" + k
            setattr(cls,get_a.__name__, get_a)
            print get_a.__name__, get_a.__doc__

class BaseObject(object):
    __metaclass__ = MetaClass
    pass

And then :

class Pers(BaseObject):
    nom = "Toune"
    prenom = "Fabien"

p = Pers()

I was expecting to have two distinct functions "p.get_nom()" and "p.get_prenom()" Btw, those two functions return the same result ("Getting value of prenom"), whereas they have distinct name and doc

What am I missing ?

Upvotes: 2

Views: 403

Answers (2)

Sven Marnach
Sven Marnach

Reputation: 601529

Change

def get_a(cls):
    print "Getting value of " + k

to

def get_a(cls, k=k):
    print "Getting value of " + k

to make this work. There is only one local variable k, and the local function get_a() will always access the current value of this variable. After finishing the loop, k will keep its last value.

Upvotes: 2

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798556

Ah yes, closures. Read that article then come back.

    for (k, v) in ra:
        setattr(cls, "_"+k, v)
        def new_method(val):
            def inner_get_a(cls):
                print "Getting value of " + val
            return inner_get_a
        get_a = new_method(k)
        get_a(cls)
        get_a.__name__ = "get_" + k
        get_a.__doc__ = "Documentation for get_" + k
        setattr(cls,get_a.__name__, get_a)
        print get_a.__name__, get_a.__doc__

Upvotes: 5

Related Questions