Python import all methods

Importing methods for a Python class

I wonder if it’s possible to keep methods for a Python class in a different file from the class definition, something like this: main_module.py:

class Instrument(Object): # Some import statement? def __init__(self): self.flag = True def direct_method(self,arg1): self.external_method(arg1, arg2) 
def external_method(self, arg1, arg2): if self.flag: #doing something #. many more methods 

In my case, to_import_from.py is machine-generated, and contains many methods. I would rather not copy-paste these into main_module.py or import them one by one, but have them all recognized as methods of the Instrument class, just as if they had been defined there:

>>> instr = Instrument() >>> instr.direct_method(arg1) >>> instr.external_method(arg1, arg2) 

8 Answers 8

People seem to be overthinking this. Methods are just function valued local variables in class construction scope. So the following works fine:

class Instrument(Object): # load external methods from to_import_from import * def __init__(self): self.flag = True def direct_method(self,arg1): self.external_method(arg1, arg2) 

To overcome the SyntaxError (Python 3.6) don’t do import * . Instead, name the methods to import explicitly, e.g. from to_import_from import method1, method2 .

It’s easier than you think:

class Instrument(Object): def __init__(self): self.flag = True def direct_method(self,arg1): self.external_method(arg1, arg2) import to_import_from Instrument.external_method = to_import_from.external_method 

Although having the machine generated code generate a class definition and subclassing from it would be a neater solution.

I don’t think what you want is directly possible in Python.

You could, however, try one of the following.

  1. When generating to_import_from.py , add the non-generated stuff there too. This way, all methods are in the same class definition.
  2. Have to_import_from.py contain a base class definition which the the Instrument class inherits.

In other words, in to_import_from.py :

class InstrumentBase(object): def external_method(self, arg1, arg2): if self.flag: . 

and then in main_module.py :

import to_import_from class Instrument(to_import_from.InstrumentBase): def __init__(self): . 

you can do this with the __getattr__ method

def external_function(arg): print("external", arg) 
import external class Instrument(object): def __getattr__(self, name): if hasattr(external, name): return getattr(external, name) else: return Object.__getattr__(self, name) def direct_method(self, arg): print("internal", arg) i = Instrument() i.direct_method("foo") i.external_function("foo") 

I’m sorry that this is kind of a «You shouldn’t be putting nails in the wall» answer, but you’re missing the point of python class definitions. You should rather put the class with all its methods in its own python file, and in your main_module.py do

from instrument import Instrument 

If you plan on using the methods for several classes, you should consider subclassing. In your case, the machine generated file could contain the base class that Instrument inherits from.

Читайте также:  Сколько времени изучать html

Finally, give your class a good docstring that explains the API to its user, so there is no need for a «header file» used as an overview of your class.

What you’re doing is extending a base class with some «machine-generated» code.

Choice 1. Extend a base class with machine-generated code.

# Start of boilerplate # import main_module class Instrument_Implementation( main_module.Instrument_Abstraction ): def direct_method(self,arg1): # End of boilerplate # . the real code. 

Your application can then import machine_generated and use machine_generated.Instrument_Implementation .

Choice 2. Simply use first-class functions.

def external_method(self, arg1, arg2): . the real code. 
import machine_generated class Instrument( object ): def direct_method(self,arg1): return machine_generator.external_method( arg1, . ) 

Your application can import main_module and use main_module.Instrument .

Here’s my try. I think a nicer approach could be made with metaclasses.

def external_method(self, arg1, arg2): if self.flag: print "flag is set" else : print "flag is not set" 
import imp import os import inspect import new import pdb class MethodImporter(object) : def __init__(self, path_to_module) : self.load_module(path_to_module) def load_module(self, path_to_module) : name = os.path.basename(path_to_module) module_file = file(path_to_module,"r") self.module = imp.load_module(name, module_file , path_to_module, ('','r',imp.PY_SOURCE)) print "Module %s imported" % self.module for method_name, method_object in inspect.getmembers(self.module, inspect.isfunction) : print "adding method %s to %s" % (method_name, self) setattr(self, method_name, new.instancemethod(method_object, self, self.__class__)) class Instrument(MethodImporter): def __init__(self): super(Instrument,self).__init__("./to_import_from.py") self.flag = True def direct_method(self,arg1): self.external_method(arg1, arg2) 
arg1, arg2 = 1, 2 instr = Instrument() instr.direct_method(arg1) instr.external_method(arg1, arg2) 
Module imported adding method external_method to flag is set flag is set 

Technically, yes this is possible, but solving it this way is not really idiomatic python, and there are likely better solutions. Here’s an example of how to do so:

import to_import_from class Instrument(object): locals().update(dict((k,v) for (k,v) in to_import_from.__dict__.iteritems() if callable(v))) def __init__(self): self.flag = True def direct_method(self,arg1): self.external_method(arg1, arg2) 

That will import all callable functions defined in to_import_from as methods of the Instrument class, as well as adding some more methods. Note: if you also want to copy global variables as instance variables, you’ll need to refine the check. Also note that it adds all callable objects it finds in to_import_from’s namespace, including imports from other modules (ie from module import some_func style imports)

Читайте также:  How to compare strings in python

However, this isn’t a terribly nice way to do it. Better would be to instead tweak your code generation to produce a class, and have your class inherit from it. This avoids the unneccessary copying of methods into Instrument’s namespace, and instead uses normal inheritcance. ie:

class Instrument(to_import_from.BaseClass): # Add new methods here. 

Источник

Import all functions and classes inside a module into a class python

I am trying to import all the objects from a subfolder into a class in python 3.8, and am strugguling to find a way to do so. I don’t want to manually have to import all the objects, as there are far too many files to list:

class Foo: from bar import

And when I use the star symbol to import all functions and classes (e.g. from bar import * ) I get the following error:

SyntaxError: import * only allowed at module level 

Also, I would not like to put everything under a sub-scope (e.g. import bar.package and put all the files in the package subpackage of bar ), because the functions in bar rely on being passed self when run and would mean would have to change all references of self to self.package I am only creating another folder with all the methods in the class so that there is not a single extremely long file. So I guess I have three questions: Why is importing all in a class not allowed, how can I get around this, and is there a better way to split multiple methods up into different files? EDIT: I’ve seen this post, and is what I currently have, but only instead of importing everything manually I want to use the * instead. EDIT 2: Perhaps creating the submethods of a class as a package and importing it as self would work (e.g. import bar.package as self ), but this may override the default self. For example say I have the two files foo.py and bar.py :

# foo.py def print_bar(self): print("bar") 
# bar.py class Test: import foo as self def __init__(self): print("hi") self.one = 1 def print_one(self): print(self.one) if __name__ == "__main__": test_class = Test() test_class.print_one() test_class.self.print_bar(test_class) 

Notice the ugly call in bar.py that runs test_class.self.print_bar(test_class) . In this case, python does not automatically pass the class as a method. If I get rid of the test_class argument passed in the function it does not run and gives a TypeError . I want to avoid passing self to the method at all costs.

Читайте также:  Make matrix in python

Источник

import everything from a module except a few methods

Is it possible to import everything ( * ) from an existing Python module except a number of explicitly specified methods? (Background: Against recommended Python practice it is common in FEniCS to do from dolfin import * . A few of the methods names contain the string «Test» though (e.g., TestFunction() ) and are mistaken for unit tests by nose.)

3 Answers 3

In case you don’t have an access to the module, you can also simply remove these methods or variables from a global namespace. Here’s how this could be done:

to_exclude = ['foo'] from somemodule import * for name in to_exclude: del globals()[name] 

Your solution does not work for flask because flask defines a namespace called globals by coincidence.

If there is just a single name to exclude you don’t have to use globals() and can simply write del foo .

__all__ = ["echo", "surround", "reverse"] #Or whatever your module names are 

to the file which has these modules, or __init__.py of the package you want to import from.

imports only the specified modules in __all__

This appears to work if you do it from outside, e.g. import somemodule; somemodule.__all__ = [‘get’, ‘these’, ‘guys’]; from somemodule import *

@alexander-zhukov’s solution will work most of the time, but not when the imported module coincidentally contains a variable called globals .

to_exclude = ['abort'] from flask import * for name in to_exclude: del globals()[name] Traceback (most recent call last): File "", line 2, in TypeError: 'module' object is not callable 

The error is because the flask package contains a namespace called globals (that cannot be called) which will overwrite your current global symbol globals .

The following solution will work for flask and others:

to_exclude = ['abort'] from flask import * for name in to_exclude: __builtins__.globals().pop(name) 

However ridiculously, it does not work if you open a Python console and type in the commands manually. I think this is a defect of Python 3. If you want this to work in a Python console, then you have to explicitly import the builtins module:

import builtins to_exclude = ['abort'] from flask import * for name in to_exclude: builtins.globals().pop(name) 

Источник

Оцените статью