Imported module as a class or instance method? - python

Is it fine to make a module an instance method or probaby class method so that child classes need not import them again if it is in another file and you can easily over-ride them? Also is class or instance method preferred here?
import submodule
class MyClass(object):
def __init__(self):
"""
"""
pass
def mysubmodule():
"""
Method that returns the submodule.
"""
return submobdule

If the child class is defined in the same file, there will be no need for a second import.
If the child class is defined in a different file, I fail to see the advantage of your idea. Add the import and every reader of the child class knows what the code is using.

Related

In Python how to call Parent class function as if I were Parent object

I have a Parent and a Child class, both should execute their own fct in init but Child have to execute first the Parent fct :
class Parent(object):
def __init__(self):
self.fct()
def fct(self):
# do some basic stuff
class Child(Parent):
def __init__(self):
super().__init__()
self.fct()
def fct(self):
# add other stuff
Problem is that super().init() calls the Child fct and not the Parent one as I would like. Of course I could rename Child function as fct2 but I was wondering if I can do what I want to do without changing names (because fct and fct2 do the same thing conceptually speaking, they just apply on different things). It would be nice if I could call super().__init() as if were Parent object.
The idea of subclassining is this: if you ever need to use a method to the parent class, just do not create it in the child class.
Otherwise, in a hierarchy with complicated classes and mixins, and you really need the methods to have the same name, there is the name mangling mechanism, triggered by Python when using two underlines __ as a method or attribute prefix:
class Parent(object):
def __init__(self):
self.__fct()
def __fct(self):
# do some basic stuff
class Child(Parent):
def __init__(self):
super().__init__()
self.__fct()
def __fct(self):
# add other stuff
Using the __ prefix makes Python change the name of this method, both in declaration and where it is used when the class is created (at the time the class statement with its block is itself executed) - and both methods work as if they were named differently, each one only accessible, in an ordinary way, from code in its own class.
Some documentation, mainly older docs, will sometimes refer to this as the mechanism in Python to create "private methods". It is not the samething, although it can serve the same purpose in some use cases (like this). The __fct method above will be renamed respectively to Parent._Parent__fct and Child._Child__fct when the code is executed.
second way, without name mangling:
Without resorting to this name mangling mechanism, it is possible to retrieve attributes from the class where a piece of code is declared by using the __class__ special name (not self.__class__, just __class__) - it is part of the same mechanism Python uses to make argumentless super() work:
class Parent(object):
def __init__(self):
__class__.fct(self) # <- retrieved from the current class (Parent)
def fct(self):
# do some basic stuff
class Child(Parent):
def __init__(self):
super().__init__()
__class__.fct(self)
def fct(self):
# add other stuff
This will also work - just note that as the methods are retrieved from the class object, not from an instance, the instance have to be explicitly passed as an argument when calling the methods.
The name __class__ is inserted automatically in any methods that use it, and will always refer to the class that has the body were it appears - the class itself will be created "in the future", when all the class body is processed and the class command itself is resolved.

calling a method inside a class from a different file

I am trying to implement python classes and objects in my application code. Currently, I have a file that includes all the frequently used functions. I import them in another file.
funcs.py
class name1():
def func1(x):
return x
def func2(y):
return y
....
file1.py
from funcs import func1
from funcs import func2
I'd like to organize the code in class, method and attributes and then invoke them in different files.
How do I call a method within a class from another file? What changes do I need to make in funcs.py file?
If you want to call a method within a class, first you have to instantiate an object of that class, and then call the method in reference to the object. Below is not an ideal implementation but it's just for example.
example.py
class MyClass:
def my_method(self):
print('something')
object1 = MyClass()
object1.my_method()
Then when you want to call the method in another file you have to first import them.
another.py
from .example import MyClass
object2 = MyClass()
object2.my_method()
If you just want to call the method without having to create an object first you can use #staticmethod.
class MyClass:
#staticmethod
def my_method(self):
print('something')
MyClass.my_method()
Yet as I said this is not the ideal implementation. As #juanpa.arrivillaga said ideally you cannot just throw in any method and bundle them into a single class. The content of a class is all related to the object you want to define as a class.

Is there a magic method to know that a base class is used through inheritance?

I'd like to describe my problem with code to make it clear:
class MyBaseClass(object):
def __init__(self):
print 'foobar'
def __call__(self):
print 'spameggs'
def __is_used__(self): # This is only a pseudo method
print 'I\'m being used! - MyBaseClass'
class MySubClass(MyBaseClass):
def __init__(self):
print 'monty python'
Now I'd like to know if there is a similar magic method __is_used__ for a class object to know if it is being use as a parent/base class of another class (sub)?
Example usage:
class_a = MySubClass()
# Output
# monty python
# I'm being used! - MyBaseClass
Use Case
To avoid confusion (I apologize). A best example would be a mixin. Example an S3Mixin.
An S3Mixin has a capabilities to upload and download file to S3 buckets.
class S3Mixin(object):
def upload(self):
def download(self):
Now i want to use it to ImageFile and VideoFile classes.
class ImageFile(S3Mixin):
# omitted lengthy properties
class VideoFile(S3Mixin):
# omitted lengthy properties
Now each object has a function to use the s3 basic functionalities. Now the real problem arise when I try to use another module inside a S3Mixin which cause a circular dependency issue. Now to avoid it I have to import it inside each function of S3Mixin. I tried putting it on the __init__ method and __call__ method which is obviously not going to work.
I don't want to do that. Instead I wanted to know if there is available method so I can import all the conflicted module preferable on a magic method of an S3Mixin.
Note:
I'm not asking for a checking of a class that is a subclass of another class. That is far from the question. I would like to know if there is a MAGIC METHOD so i can further create a logic in it when a base class is used.

How to get filename of subclass?

How to get the filename of the subclass?
Example:
base.py:
class BaseClass:
def __init__(self):
# How to get the path "./main1.py"?
main1.py:
from base import BaseClass
class MainClass1(BaseClass):
pass
Remember that self in BaseClass.__init__ is an instance of the actual class that's being initialised. Therefore, one solution, is to ask that class which module it came from, and then from the path for that module:
import importlib
class BaseClass:
def __init__(self):
m = importlib.import_module(self.__module__)
print m.__file__
I think there are probably a number of way you could end up with a module that you can't import though; this doesn't feel like the most robust solution.
If all you're trying to do is identify where the subclass came from, then probably combining the module name and class name is sufficient, since that should uniquely identify it:
class BaseClass:
def __init__(self):
print "{}.{}".format(
self.__module__,
self.__class__.__name__
)
You could do it by reaching back through the calling stack to get the global namespace of the caller of the BaseClass.__init__() method, and from that you can extract the name of the file it is in by using the value of the __file__ key in that namespace.
Here's what I mean:
base.py:
import sys
class BaseClass(object):
def __init__(self):
print('In BaseClass.__init__()')
callers_path = sys._getframe(1).f_globals['__file__']
print(' callers_path:', callers_path)
main1.py:
from base import BaseClass
class MainClass1(BaseClass):
def __init(self):
super().__init__()
mainclass1 = MainClass1()
Sample output of running main1.py:
In BaseClass.__init__()
callers_path: the\path\to\main1.py
I think you're looking to the wrong mechanism for your solution. Your comments suggest that what you want is an exception handler with minimal trace-back capability. This is not something readily handled within the general class mechanism.
Rather, you should look into Python's stack inspection capabilities. Very simply, you want your __init__ method to report the file name of the calling sub-class. You can hammer this by requiring the caller to pass its own __file__ value. In automated fashion, you can dig back one stack frame and access __file__ via that context record. Note that this approach assumes that the only time you need this information is when __init__ is called is directly from a sub-class method.
Is that enough to get you to the right documentation?

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.py
- test.py
__init__.py has this code
import os
for module in os.listdir(os.path.dirname(__file__)+"/."):
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
del module
main.py has this code as of now
from lib.index import *
print User.__dict__
index.py has this code
class User(object):
def test(self):
return "hi"
pass
test.py has this code
class User(object):
def tes2(self):
return "hello"
When I execute main.py it successfully prints the method test from index.py but what I am trying to do is figure out a way where I can just create a file in the lib folder where that while has only one function in the format
class User(object):
def newFunction(self):
return abc
and this function should automatically be available for me in main.py
I am sure that this is not a hard thing to do but I honestly don't know what I want (what to search for to solve this) which is preventing me from researching the solution.
You can use a metaclass to customize class creation and add functions defined elsewhere:
import types
import os
import os.path
import imp
class PluginMeta(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 in dir(module):
function = getattr(module, name)
if isinstance(function, types.FunctionType):
dct[function.__name__] = function
return type.__new__(cls, name, bases, dct)
class User(metaclass=PluginMeta):
plugindir = "path/to/the/plugindir"
def foo(self):
print "foo"
user = User()
print dir(user)
Then in the plugin files, just create functions not classes:
def newFunction(self, abc):
self.abc = abc
return self.abc
And the metaclass will find them, turn them into methods, and attach them to your class.
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:
class User(object):
pass
def newFunction(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:
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?
If you have more than one class you're extending this way, how do you determine what goes in which class?
At what point(s) in your program does the auto-extension happen?
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?
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.
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 import CPU, CPUBase
import cpu_common
import cpu_ext
cpu_base.py:
def getClass():
return __cpu__
def setClass(CPUClass):
global __cpu__
__cpu__ = CPUClass
__classes__.append(CPUClass)
def CPU(*kw):
return __cpu__(*kw)
class CPUBase:
def __init__(self):
your_init_Stuff
# optionally a method classname_constructor to mimic __init__ for each one
for c in __classes__:
constructor = getattr(c, c.__name__ + '_constructor', None)
if constructor is not None:
constructor(self)
setClass(CPUBase)
cpu_common.py:
from cpu_base import getClass, setClass
class CPUCommon(getClass()):
def CPUCommon_constructor(self):
pass
setClass(CPUCommon)
cpu_ext.py:
from cpu_base import getClass, setClass
class CPUExt(getClass()):
pass
setClass(CPUExt)
to use the class import CPU from cpu.py

Categories

Resources