Welcome, guest | Sign In | My Account | Store | Cart

some simple functions for dynamically adding methods, properties,and classmethods to classes at runtime

Python, 128 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python
#-----------------------------------------------------------------------------
#   Copyright 2003 by Bud P. Bruegger, Sistema, Italy
#   mailto:bud@sistema.it
#   http://www.sistema.it
#-----------------------------------------------------------------------------
#   dynClass -- Dynamic Classes
#   ---------------------------
#   
#   some simple functions for dynamically adding methods, properties
#   and classmethods to classes at runtime.  
#   
#-----------------------------------------------------------------------------

# see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732 
# and http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81982
# and http://www.python.org/2.2/descrintro.html#property


import new
import sys

def addMethod(classInstance, func, methName=None):
    """adds function as a new method to an existing class
       function should have self as first argument
    """
    meth = new.instancemethod(func, None, classInstance)
    name = methName or func.__name__
    setattr(classInstance, name, meth)
    return name

def addProperty(classInstance, attrName, fget, fset, fdel=None, \
              fdoc="this is magic"):
    """adds a property to an existing class """
    prop = property(fget, fset, fdel, fdoc)
    setattr(classInstance, attrName, prop)

def addClassMethod(classInstance, func, methName=None):
    """adds function as a new class method to an existing class.
       function should have self as first argument
    """
    name = methName or func.__name__
    setattr(classInstance, name, classmethod(func))

def classFromName(className):
    "returns the class instance object"
    return getattr(sys.modules['__main__'], className)

#==========  example usage ====================================================

if __name__ == "__main__":
    pass 

    #-- testing addMethod ------------------

    def func1(self):
        "some test function"
        return "Name is %s" % self._name
    
    def func2(self, comment=''):
        "some test function"
        return "Age is %s %s" % (self._age, comment)
    
    class Example(object):
        "some example class"
    
        def __init__(self, name, age):
            self._name = name
            self._age = age
    
    sarah = Example('Sarah', 5)
    josh = Example('Josh', 2)
    
    addMethod(Example, func1, 'getName')
    addMethod(Example, func2, 'getAge')
    
    lucia = Example('Lucia', 20)
    
    # Does it work as expected?
    
    print sarah.getName()
    print sarah.getAge('at least soon')
    print josh.getName()
    print josh.getAge('and wild')
    print lucia.getName()
    print lucia.getAge('some time ago')
    print "\n-----------------------\n"
    
    
    #-- testing properties ------------------
    
    def getAltName(self):
        return "*" + self._name + "*"
    
    def setAltName(self, val):
        self._name = val[1:-1]
    
    addProperty(Example, 'altName', getAltName, setAltName)
    print sarah.altName
    sarah.altName="*NEW-SARAH*"
    print sarah.altName
    print sarah.getName()
    bud = Example('Bud', 42)
    print bud.altName
    bud.altName="*The king of beers*"
    print bud.altName
    print bud.getName()
    print "\n-----------------------\n"
    
    #-- testing classFromName -----------

    print "The class named 'Example' is %s" % classFromName('Example')
    class EEE(object):
        pass
    print "The class named 'EEE' is %s" % classFromName('EEE')
    print "\n-----------------------\n"

    
    #-- testing addClassMethod -----------------------

    class C(object):
        pass
    def func(cls):
        return "<<%s>>" % cls.__name__

    addClassMethod(C, func, 'className')

    print "the class name is: ", C.className()

It is sometimes useful to modify classes at runtime, for example to implement some weakly coupled persistance mechanism for user-defined classes. While some recipes already address related issues (see links in code), this submission attempts to consolidate them in a single reusable module.

Created by Bud P. Bruegger on Thu, 22 May 2003 (PSF)
Python recipes (4591)
Bud P. Bruegger's recipes (1)

Required Modules

Other Information and Tasks