Skip to content Skip to sidebar Skip to footer

Adding Functions From Other Files To A Python Class

I am having trouble with this setup mainly because I am not sure what I actually want in order to solve this problem. This is the setup - main.py - lib - __init__.py - index.p

Solution 1:

You can use a metaclass to customize class creation and add functions defined elsewhere:

import types
import os
import os.path
import imp

classPluginMeta(type):
    def__new__(cls, name, bases, dct):
        modules = [imp.load_source(filename, os.path.join(dct['plugindir'], filename))
                    for filename in os.listdir(dct['plugindir']) if filename.endswith('.py')]
        for module in modules:
            for name indir(module):
                function = getattr(module, name)
                ifisinstance(function, types.FunctionType):
                    dct[function.__name__] = function
        returntype.__new__(cls, name, bases, dct)


classUser(object):
    __metaclass__ = PluginMeta
    plugindir = "path/to/the/plugindir"deffoo(self):
        print"foo"

user = User()
printdir(user)

Then in the plugin files, just create functions not classes:

defnewFunction(self, abc):
    self.abc = abc
    returnself.abc

And the metaclass will find them, turn them into methods, and attach them to your class.

Solution 2:

Classes are objects, and methods are nothing more than attributes on class-objects.

So if you want to add a method to an existing class, outside the original class block, all that is is the problem of adding an attribute to an object, which I would hope you know how to do:

classUser(object):
    passdefnewFunction(self):
    return'foo'

User.newFunction = newFunction

agf's metaclass answer is basically a nifty automatic way of doing this, although it works by adding extra definitions to the class block before the class is created, rather than adding extra attributes to the class object afterwards.

That should be basically all you need to develop a framework in which things defined in one module are automatically added to a class defined elsewhere. But you still need to make a number of design decisions, such as:

  1. If your externally-defined functions need auxiliary definitions, how do you determine what's supposed to get added to the class and what was just a dependency?
  2. If you have more than one class you're extending this way, how do you determine what goes in which class?
  3. At what point(s) in your program does the auto-extension happen?
  4. Do you want to say in your class "this class has extensions defined elsewhere", or say in your extensions "this is an extension to a class defined elsewhere", or neither and somewhere bind extensions to classes externally from both?
  5. Do you need to be able to have multiple versions of the "same" class with different extensions active at the same time?

A metaclass such as proposed by agf can be a very good way of implementing this sort of framework, because it lets you put all the complex code in one place while still "tagging" every class that doesn't work the way classes normally work. It does fix the answers to some of the questions I posed above, though.

Solution 3:

here a working code we used in a project, I'm not sure it's the best way but it worked and there is almost no additional code to add to other files

cpu.py:

from cpu_base importCPU, CPUBaseimport cpu_common
import cpu_ext

cpu_base.py:

defgetClass():
    return __cpu__

defsetClass(CPUClass):
    global __cpu__
    __cpu__ = CPUClass
    __classes__.append(CPUClass)

defCPU(*kw):
    return __cpu__(*kw)

classCPUBase:
    def__init__(self):
        your_init_Stuff
        # optionally a method classname_constructor to mimic __init__ for each onefor c in __classes__:
            constructor = getattr(c, c.__name__ + '_constructor', None)
            if constructor isnotNone:
                constructor(self)
setClass(CPUBase)

cpu_common.py:

from cpu_base import getClass, setClass
classCPUCommon(getClass()):
    defCPUCommon_constructor(self):
        pass
setClass(CPUCommon)

cpu_ext.py:

from cpu_base import getClass, setClass

classCPUExt(getClass()):
    pass
setClass(CPUExt)

to use the class import CPU from cpu.py

Post a Comment for "Adding Functions From Other Files To A Python Class"