Welcome, guest | Sign In | My Account | Store | Cart
def installmethod(function, object, name = None):
	"""
	This function adds either a bound method to an instance or
	an unbound method to a class. If name is ommited it defaults
	to the name of the given function.
	Example:
	  a = A()
	  def f(self, x, y):
	    self.z = x + y
	  installmethod(f, A, "add")
	  a.add(2, 4)
	  print a.z
	  installmethod(lambda self, i: self.l[i], a, "listIndex")
	  print a.listIndex(5)
	"""
	from types import ClassType, MethodType, InstanceType
	if name == None:
		name = function.func_name
	else:
		function = renamefunction(function, name)
	if type(object) == ClassType:
		setattr(object, name,
				MethodType(function, None, object))
	elif type(object) == InstanceType:
		setattr(object, name,
				MethodType(function, object, object.__class__))
	else:
		raise TypeError

def renamefunction(function, name):
	"""
	This function returns a function identical to the given one, but
	with the given name.
	"""
	from types import FunctionType, CodeType

	c = function.func_code
	if c.co_name != name:
		# rename the code object.
		c = CodeType(c.co_argcount, c.co_nlocals, c.co_stacksize,
					 c.co_flags, c.co_code, c.co_consts,
					 c.co_names, c.co_varnames, c.co_filename,
					 name, c.co_firstlineno, c.co_lnotab)
	if function.func_defaults != None:
		return FunctionType(c, function.func_globals, name,
							function.func_defaults)
	return FunctionType(c, function.func_globals, name)


if __name__ == '__main__':
	# example
	class Widget:
		def installButton(self, name):
			def f(self, name=name):
				print name, 'pressed'
			installmethod(f, self, name)
			
	a = Widget()
	a.installButton('foo')
	a.foo()
	# AttributeError: Widget().foo()
	
	def f(self, x, y):
		self.z = x + y
	Widget.add = renamefunction(f, "add")
	a.add(2, 4)
	print a.z
	installmethod(lambda self, i: self.l[i], Widget, "listIndex")
	a.l = list("abc")
	print a.listIndex(1)
	
	# TypeError: a.add(2, 4, 6)

History