Modules with Classes and Imports - python

If I were to use a class in a module how would I make it "top level" in it's instance?
Structure:
/package
__init__.py
/subPackage
__init__.py
module.py
subModule.py
/theScript.py
python theScript.py
Source of theScript:
import package.subPackage.module
package.subPackage.module.method()
Source of /package/subPackage/module.py:
class module:
def method(self): pass
moduleInstance = module()
I guess what I am asking is how would I make it so that I don't have to do package.subPackage.module.moduleInstance.method() and could package.subPackage.module.method()
I know I can just remove the class and instance but I prefer the class because it makes it easier to subclass later if somebody wants to without needing to modify our source directly but if I ultimately have to I will just use methods instead of class/method in module.

Here is how the random module in the standard lib solved this problem:
_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
triangular = _inst.triangular
...
Seems a reasonable solution to me. Of course there is the drawback that you have to manually keep the method lists in sync, but the worst thing that will happen if you forget to add a method name is an error message that tells you exactly what is missing.

Related

How to convert a "custom class"-based singleton object programmatically into a python module?

I would like to convert a singleton-object programmatically into a Python module so that I can use the methods of this singleton-object directly by importing them via the module instead of accessing them as object attributes. By "programmatically" I mean that I do not want to have to copy-paste the class methods explicitly into a module file. I need some sort of a workaround that allows me to import the object methods into to global scope of another module.
I would really appreciate if someone could help me on this one.
Here is a basic example that should illustrate my problem:
mymodule.py
class MyClass:
"""This is my custom class"""
def my_method(self):
return "myValue"
singleton = MyClass()
main_as_is.py
from mymodule import MyClass
myobject = MyClass()
print(myobject.my_method())
main_to_be.py
from mymodule import my_method # or from mymodule.singleton import my_method
print(my_method())
You can use the same strategy that the standard random module uses. All the functions in that module are actually methods of a "private" instance of the Random class. That's convenient for most common uses of the module, although sometimes it's useful to create your own instances of Random so that you can have multiple independent random streams.
I've adapted your code to illustrate that technique. I named the class and its instance with a single leading underscore, since that's the usual convention in Python to signify a private name, but bear in mind it's simply a convention, Python doesn't do anything to enforce this privacy.
mymodule.py
class _MyClass:
""" This is my custom class """
def my_method(self):
return "myValue"
_myclass = _MyClass()
my_method = _myclass.my_method
main_to_be.py
from mymodule import my_method
print(my_method())
output
myValue
BTW, the from mymodule import method1, method2 syntax is ok if you only import a small number of names, or it's clear from the name which module it's from (like math module functions and constants), and you don't import from many modules. Otherwise it's better to use this sort of syntax
import mymodule as mm
# Call a method from the module
mm.method1()
That way it's obvious which names are local, and which ones are imported and where they're imported from. Sure, it's a little more typing, but it makes the code a whole lot more readable. And it eliminates the possibility of name collisions.
FWIW, here's a way to automate adding all of the _myclass methods without explicitly listing them (but remember "explicit is better than implicit"). At the end of "mymodule.py", in place of my_method = _myclass.my_method, add this:
globals().update({k: getattr(_myclass, k) for k in _MyClass.__dict__
if not k.startswith('__')})
I'm not comfortable with recommending this, since it directly injects items into the globals() dict. Note that that code will add all class attributes, not just methods.
In your question you talk about singleton objects. We don't normally use singletons in Python, and many programmers in various OOP languages consider them to be an anti-pattern. See https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern for details. For this application there is absolutely no need at all to use a singleton. If you only want a single instance of _MyClass then simply don't create another instance of it, just use the instance that mymodule creates for you. But if your boss insists that you must use a singleton, please see the example code here.

python import nested class

I'm new to python. This is not my actual case, it's just my curiosity about importing nested class.
So I have a main.py and test.py.
test.py:
class one():
class two():
def twodef():
pass
so in my main.py, I can do 'import test' or 'from test import one'. But I got error when do: 'from test.one import two'.
error : ImportError: No module named one
Anyone can explain this?
You can only do from module import name for names that exist in the module's global scope - basically, names that are defined in top-level module code. Names that are defined in lower-level scopes - for example within classes as in your example - are not importable. You need to import the object that contains the name, and access it from there.
from test import one
my_two = one.two()
You could do the following:
from test import one
two_object = one.two()
two_object.twodef()
inside test.py
class One:
class Two:
#staticmethod
def twodef():
print("twodef")
My main logic:
from test import One
two_obj = One.Two
two_obj.twodef()
Remove the parenthesis at the end of class definition.
Coding standards:
Always declare your class names in upper camel case (class one => class One).
For more about scope
Preference:
And if you have a single class inside python file, always name that file in that class name but in lower camel case. (test.py => one.py). I have thought this as a standard earlier, but seems its practiced widely. I would use this because, if then project size grew and if you end up having a lot of classes and modules, it's logical and easy to access, rather than visiting the module to find the class name.
Ref1
Ref2

Limit which classes in a .py file are importable from elsewhere

I have a python source file with a class defined in it, and a class from another module imported into it. Essentially, this structure:
from parent import SuperClass
from other import ClassA
class ClassB(SuperClass):
def __init__(self): pass
What I want to do is look in this module for all the classes defined in there, and only to find ClassB (and to overlook ClassA). Both ClassA and ClassB extend SuperClass.
The reason for this is that I have a directory of plugins which are loaded at runtime, and I get a full list of the plugin classes by introspecting on each .py file and loading the classes which extend SuperClass. In this particular case, ClassB uses the plugin ClassA to do some work for it, so is dependent upon it (ClassA, meanwhile, is not dependent on ClassB). The problem is that when I load the plugins from the directory, I get 2 instances of ClassA, as it gets one from ClassA's file, and one from ClassB's file.
For packages there is the approach:
__all__ = ['module_a', 'module-b']
to explicitly list the modules that you can import, but this lives in the __init__.py file, and each of the plugins is a .py file not a directory in its own right.
The question, then, is: can I limit access to the classes in a .py file, or do I have to make each one of them a directory with its own init file? Or, is there some other clever way that I could distinguish between these two classes?
You meant "for packages there is the approach...". Actually, that works for every module (__init__.py is a module, just with special semantics). Use __all__ inside the plugin modules and that's it.
But remember: __all__ only limits what you import using from xxxx import *; you can still access the rest of the module, and there's no way to avoid that using the standard Python import mechanism.
If you're using some kind of active introspection technique (eg. exploring the namespace in the module and then importing classes from it), you could check if the class comes from the same file as the module itself.
You could also implement your own import mechanism (using importlib, for example), but that may be overkill...
Edit: for the "check if the class come from the same module":
Say that I have two modules, mod1.py:
class A(object):
pass
and mod2.py:
from mod1 import A
class B(object):
pass
Now, if I do:
from mod2 import *
I've imported both A and B. But...
>>> A
<class 'mod1.A'>
>>> B
<class 'mod2.B'>
as you see, the classes carry information about where did they originate. And actually you can check it right away:
>>> A.__module__
'mod1'
>>> B.__module__
'mod2'
Using that information you can discriminate them easily.

Python - can a class act like a module?

I'm considering a package implementation set up like this:
wordproc
__init__.py
_generic.py
gedit.py
oofice.py
word.py
_generic.py would have a class like this:
class WordProc (object):
def __init__ (self):
pass
def createNewDoc (self):
print "createNewDoc unimplemented in current interface"
def getWordCount (self):
print "getWordCount unimplemented in current interface"
etc...
These could print out as shown, or raise errors. App-specific modules would just be copies of _generic.py with the WordProc classes deriving from _generic.WordProc. In this way, functionality could be implemented iteratively over time, with messages about unimplemented things simply raising alerts.
I'm imagining that __init__.py could look for the following things (listed in order) to figure out which module to use:
a wordproc module variable
a settings file in the path
a wordproc environment variable
a function that attempts to determine the environment
a default in __init__.py (probably _generic.py)
I think 3 could be a function in each app's module, or these could go into folders with particularly named environment test scripts (e.g. env.py), and __init__.py could loop over them.
I'd like then in any libraries that want to use wordproc to simply be able to do this:
import wordproc as wp
wp.createNewDoc()
etc...
What I don't know is how to have wp resolve to the proper class in the proper module as determined by __init__.py. It doesn't make sense to do this:
import wordproc.gedit as wp
This destroys the point of having __init__.py determine which module in wordproc to use. I need something like class inheritance, but on the module level.
You can achieve your desired effect by writing __init__.py like this:
Import the appropriate module first. See python docs on importlib.import_module or __import__ for help on dynamic imports.
Instantiate the class from which you want to export methods
Assign the instance methods to locals()
# import appropriate module as mod depending on settings, environment
# using importlib.import_module, or __import__
__all__ = []
_instance = mod.WordProc()
for attr in dir(_instance):
if not attr.startswith('_') and callable(getattr(_instance, attr)):
locals()[attr] = getattr(_instance, attr)

Python imports issue

I have a Utilities module which defines a few functions which are repeatedly used and am also adding in some constants. I'm running into trouble importing these constants though...
Let's say I'm working in class A, and I have a class in my constants also named A
from Utils.Constants import A as DistinctA
class A(object):
.... Implementation ....
some_var = DistinctA.SOME_CONSTANT
class Utils(object):
class Constants(object):
class A(object):
SOME_CONSTANT = "Constant"
I'm probably making this too much like Java, so if so just yell / smack my knuckles with a ruler.
When I attempt to import that class, I get an error that there is no module named Constants. What's this python newbie missing?
The identifier after 'from' must point to a module; you can't refer to a class. While I'm not qualified to say whether your nested classes are 'pythonic', I have never seen it done like that before. I'd be more inclined to create a constants.py module that contains the A class. Then you could do this:
from constants import A as DistinctA
If you really want those constants to live inside utils, you could make utils a package:
utils/
utils/__init__.py
utils/constants.py
Then you can do:
from utils.constants import A as DistinctA

Categories