dynamic method in python

  • Last Update :
  • Techknowledgy :

Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object.,Python is a dynamic programming language and due to its flexibility Python has a significant advantage over statically typed languages. Python Code can be dynamically imported and classes can be dynamically created at run-time.,In the above program, class Geeks is dynamically created which has a constructor. The data members of Geeks are string_attribute and int_attribute and member functions of Geeks are displayMethod() and classMethod(). An object obj of class Geeks is created and all the data members are assigned and displayed, all the member functions of Geeks are also called.,A class defines a collection of instance variables and methods to specify an object type. A class can be used to make as many object instances of the type of object as needed. An object is an identified entity with certain attributes (data members) and behaviours (member functions). Group of objects having similar characteristics and behaviour are the instance of the same class.

Syntax:

type(object)

Output:

class 'str'
class 'int'

Classes can be created dynamically using the below syntax:
Syntax:

type(name, bases, attributes)

Parameters:
   name: The user defined name of the class
bases: A list of base classes, and its type is tuple
attributes: the data members and methods contained in the class

Suggestion : 2

Based on Theran's code, but extending it to methods on classes:

class Dynamo(object):
   pass

def add_dynamo(cls, i):
   def innerdynamo(self):
   print "in dynamo %d" % i
innerdynamo.__doc__ = "docstring for dynamo%d" % i
innerdynamo.__name__ = "dynamo%d" % i
setattr(cls, innerdynamo.__name__, innerdynamo)

for i in range(2):
   add_dynamo(Dynamo, i)

d = Dynamo()
d.dynamo0()
d.dynamo1()

Which should print:

in dynamo 0
   in dynamo 1

Here's a snippet out of the interpreter:

>>> def makedynamo(i):
   ...def innerdynamo():
   ...print "in dynamo %d" % i
   ...innerdynamo.__doc__ = "docstring for dynamo%d" % i
   ...innerdynamo.__name__ = "dynamo%d" % i
   ...
   return innerdynamo

      >>>
      dynamo10 = makedynamo(10) >>>
      help(dynamo10)
Help on
function dynamo10 in module __main__:

   dynamo10()
docstring
for dynamo10

Python will let you declare a function in a function, so you don't have to do the exec trickery.

def __init__(self):

   def dynamo(self, arg):
   ""
" dynamo's a dynamic method!
""
"
self.weight += 1
return arg * self.weight
self.weight = 50

setattr(self.__class__, 'dynamo', dynamo)

If you want to have several versions of the function, you can put all of this in a loop and vary what you name them in the setattr function:

def __init__(self):

   for i in range(0, 10):

   def dynamo(self, arg, i = i):
   ""
" dynamo's a dynamic method!
""
"
self.weight += i
return arg * self.weight

setattr(self.__class__, 'dynamo_' + i, dynamo)
self.weight = 50

Edit: You can set the docstring via dynamo.__doc__, so you could do something like this in your loop body:

dynamo.__doc__ = "Adds %s to the weight" % i
class Dynamo(object):
   def __init__(self):
   pass

@staticmethod
def init(initData = None):
   if initData is not None:
   dynamo = Dynamo()
for name, value in initData.items():
   code = ''
'
def % s(self, * args, ** kwargs):
   %
   s ''
' % (name, value)
result = {}
exec code.strip() in result
setattr(dynamo.__class__, name, result[name])

return dynamo

return None

service = Dynamo.init({
   'fnc1': 'pass'
})
service.fnc1()

Code

class Dummy(object):

   def _mirror(self, method, * args, ** kwargs):
   ""
"doc _mirror"
""
return args, kwargs

def __getattr__(self, method):
   "doc __getattr__"

def tmp( * args, ** kwargs):
   ""
"doc tmp"
""
return self._mirror(method, * args, ** kwargs)
tmp.__doc__ = (
   'generated docstring, access by {:}.__doc__'
   .format(method))
return tmp

d = Dummy()
print(d.test2('asd', level = 0), d.test.__doc__)
print(d.whatever_method(7, 99, par = None), d.whatever_method.__doc__)

Output

(('asd', ), {
   'level': 0
}) generated docstring, access by test.__doc__((7, 99), {
   'par': None
}) generated docstring, access by whatever_method.__doc__

first, i create a list of mapping between the menu item and the frame.

menus = [(self.menuItemFile, FileFrame), (self.menuItemEdit, EditFrame)]

the first item on the mapping is the menu item and the last item is the frame to be opened. Next, i bind the wx.EVT_MENU event from each of the menu item to particular frame.

for menu in menus:
   f = genfunc(self, menu[1])
self.Bind(wx.EVT_MENU, f, menu[0])

genfunc function is the dynamic function builder, here is the code:

def genfunc(parent, form):
   def OnClick(event):
   f = form(parent)
f.Maximize()
f.Show()
return OnClick

Suggestion : 3

I recently wanted to dynamically add methods to a Python class based on a list of relationships. The model class, Animal, was related to a number of description classes like Color and Sound. For a given animal, I wanted to be able to easily get the values for its descriptions, such as:,For simplicity, I’ve swapped out the code that traverses the class relationships and instead stored the descriptions directly in the Animal class. Here’s the class simplified for this blog post, along with the list of descriptions available:,Although I could have simply written non-dynamic methods like color_values, noise_values, etc. in the Animal class, I had already defined a list of the relevant class names and I prefer not repeating code. So instead I dove into Python’s dynamic pool.,Just because a method is dynamic doesn’t mean it can’t be properly documented. Besides code comments around the definition of the method, a dynamically added methods should have its name and doc attributes set. The name attribute is particularly important for readable stack traces.

I recently wanted to dynamically add methods to a Python class based on a list of relationships. The model class, Animal, was related to a number of description classes like Color and Sound. For a given animal, I wanted to be able to easily get the values for its descriptions, such as:

elephant.color_values()
# => ['gray', 'silver', 'taupe']

For simplicity, I’ve swapped out the code that traverses the class relationships and instead stored the descriptions directly in the Animal class. Here’s the class simplified for this blog post, along with the list of descriptions available:

class Animal:
   descriptions = {}

def __init__(self, name, colors, sounds):
   self.name = name
self.descriptions['color'] = colors
self.descriptions['sound'] = sounds

description_names = ['color', 'sound']

And a cat to play with:

cat = Animal('cat', colors = ['red', 'orange'], sounds = ['purr', 'meow'])

But if the method names are unknown, or in this case I’m trying to avoid repeating them, things get a little more complicated. Instead of explicitly typing out the method name, the name comes from a variable, and is set on the class using the setattr method.

def add_description_fn(description):
   fn_name = description + '_values'

def fn(self):
   print "{0}: {1}".format(self.name, self.descriptions[description])
setattr(Animal, fn_name, fn)

for description in description_names:
   add_description_fn(description)

cat.color_values()
# => cat: ['red', 'orange']
cat.sound_values()
# => cat: ['purr', 'meow']

In my first pass at this problem, I created the dynamic methods directly in the for-loop and was baffled why .color_values() was returning sounds rather than colors. The problem was caused by Python’s unusual for-loop variable scoping (described in some detail in this scope resolution guide, and also by Fran Bull in an earlier post on Python gotchas that I clearly didn’t take to heart). As I learned from this exercise, the loop variable defined in a for-loop exists at the block level that contains the for-loop. Here’s code to illustrate the issue:

fns = {}
for i in ['a', 'b']:
   fns[i] = lambda: i
print i
# => b
print fns['a']()
# => b
print fns['b']()
# => b

Suggestion : 4

? Python’s built-in exec() executes the Python code you pass as a string or executable object argument. This is called dynamic execution because, in contrast to normal static Python code, you can generate code and execute it at runtime. This way, you can run programmatically-created Python code.,The exec() function can take any source code as a string and run it within your script. It’s the perfect way to dynamically create a function in Python!,However, this can hardly be considered elegant code because of the manual labor involved in copy&pasting and the unnecessary space required to do it. ,First, define the factory function that dynamically creates a local function f only visible within the scope of the current function execution. The function f can do all the custom things you want it to do.

For example, you may want to define ten functions f_0, f_1, …, f_9 programmatically that do something such as printing its function identifier. You could do the following:

def f_0(): print(0)
def f_1(): print(1)
def f_2(): print(2)
def f_3(): print(3)
def f_4(): print(4)
def f_5(): print(5)
def f_6(): print(6)
def f_7(): print(7)
def f_8(): print(8)
def f_9(): print(9)

f_0()
f_1()
f_2()
f_3()
f_4()
f_5()
f_6()
f_7()
f_8()
f_9()

The desired output would be:

0
1
2
3
4
5
6
7
8
9

Here’s how you can use the exec() function to define 10 functions programmatically and run them afterwards:

# Define functions f_0 to f_9
for i in range(10):
   exec(f "def f_{i}(): print({i})")

# Run functions f_0 to f_9
for i in range(10):
   exec(f "f_{i}()")

You can use the dir() function to check out whether the functions are really defined in the namespace:

>>> dir()['__annotations__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'f_0', 'f_1', 'f_2', 'f_3', 'f_4', 'f_5', 'f_6', 'f_7', 'f_8', 'f_9', 'i']

A more elegant way to solve our problem would be to create a function factory—a function that creates other functions programmatically and returns them as function objects. You can then use the callable objects to run the dynamically-created functions.

# Define factory
def factory(argument):
   def f():
   print(argument)

return f

# Define functions
functions = []
for i in range(10):
   functions.append(factory(i))

# Run functions
for f in functions:
   f()

Suggestion : 5

By Bernd Klein. Last modified: 01 Feb 2022.

x = [4, 5, 9]
y = "Hello"
print(type(x), type(y))
<class 'list'>
   <class 'str'>
print(type(list), type(str))
<class 'type'>
   <class 'type'>
x = [4, 5, 9]
y = "Hello"
print(type(x), type(y))
print(type(type(x)), type(type(y)))
<class 'list'>
   <class 'str'>
      <class 'type'>
         <class 'type'>

Suggestion : 6

The first three arguments are the components that make up a class definition header: the class name, the base classes (in order), the keyword arguments (such as metaclass).,The arguments are the components that make up a class definition header: the class name, the base classes (in order) and the keyword arguments (such as metaclass).,Creates a class object dynamically using the appropriate metaclass.,The exec_body argument is a callback that is used to populate the freshly created class namespace. It should accept the class namespace as its sole argument and update the namespace directly with the class contents. If no callback is provided, it has the same effect as passing in lambda ns: None.

>>> from types
import GenericAlias

   >>>
   list[int] == GenericAlias(list, (int, ))
True
   >>>
   dict[str, int] == GenericAlias(dict, (str, int))
True
class SimpleNamespace:
   def __init__(self, /, **kwargs):
      self.__dict__.update(kwargs)

      def __repr__(self):
      items = (f "{k}={v!r}"
         for k, v in self.__dict__.items()) return "{}({})".format(type(self).__name__, ", ".join(items))

      def __eq__(self, other):
      if isinstance(self, SimpleNamespace) and isinstance(other, SimpleNamespace):
      return self.__dict__ == other.__dict__
      return NotImplemented