Import class from file of the same name - python

I often do this:
└─ mymodule
├─__init__.py
├─ MyClass1.py
...
└─ MyClass2.py
And each file contains a single class, named accordingly MyClass1, MyClass2.
I know, I know, not pythonic of me, but I believe that convention should not limit my possibilities.
But, I encounter problems that I can not solve on my own - python import rules defy my logic.
Could you please help me, if not understand, but at least to have a way to do what I want. I want to compose my __init__.py so, that "mymodule" behaves as if all classes were in one file "mymodule.py".
I.e. from outside file, I want to be able to do:
from mymodule import MyClass1
And it would give me the class, and not the module, without having to do MyClass1.MyClass1.
Is there a way to do this in Python?

You can import it like this:
from mymodule.MyClass1 import MyClass1

In __init__.py:
from .MyClass1 import MyClass1
from .MyClass2 import MyClass2
Then you can use your import:
from mymodule import MyClass1

Related

Group a collection of module files in a directory into a single import

I have a python application that has grown in size and complexity. I now have 2 folders - one that contain some utility classes and another that contains some other classes. It's quite a long list in each and the classes are referenced all over the place.
MyApp Folder
main_app.py
-- states
- Class1.py
- Class2.py
-- util
- Util1.py
- Util2.py
In main_ap.py is there a way I can just do import states and then reference any classes within that folder as states.Class1? I'd do the same for the util folder but the difference there is some of these classes reference each other.
I've tried __init__.py and some other things but i'm a legacy C++/C developer and relatively new to Python and i think this is handled much differently.
So __init__.py is a file that is executed the first time when you access something inside that package.
Saying that, import states is a way to execute content of states/__init__.py
# states/__init__.py
from states.Class1 import MyClass
# Or with relative path
from .Class2 import MyClass as MyClass2
# main_app.py
import states
states.MyClass() # It works
from states import MyClass2
MyClass2() # It works too.
In case you decide to use asterisk import (as Eldamir stated) you can be interested in __all__ keyword.
If states.__init__.py does from .Class1 import * and from .Class2 import *, then main.py can do import states and then states.SomeClassFromClass1Module
define a __init__.py file and then import the classes you want in the __init__.py file eg from class1 import class11 then at last define __all__ method and write all the class name which you want to be used as states.class11 as __all__ = ['class11', 'class12',.. ]

How to call a class outside of the file

I am an APCS student so my primary language is Java but am currently writing a program that requires python which I know somewhat. I assume there is a way to call classes / methods outside the file in which they were created like in Java because they are both OO, but was wondering how I would go about doing this. Thanks.
Depending on how you go about packaging your code (IE: you may end up using a python package or simply a module) you will likely use the import statement in a very similar way as you do java. Some Examples:
import my_module
my_object = my_module.MyClass()
or
from my_module import MyClass
my_object = MyClass()
You use the import statement, where you either import the whole file or just the required class.
For example, my directory has file1.py and file2.py.
file2.py has a class named "A", which has the method print_hi().
So, in file1.py I do this:
from file2 import A
A.print_hi()
And I get the expected output.
Or, I could do this:
import file2
file2.A.print_hi()
which gives me the same output.But, you can't just import a method from a class which is present in another file --- you either import the file or the required class.
Thus, doing things like:
from file2.A import print_hi
or
from file2 import A.print_hi
won't work.

does import module(or package).function actually import the whole module / package?

Say I want to
import module.function
does it actually imported the whole module into memory instead of just the function?
I want to ask this question because I thought only importing the function I need from a module reduces memory consumption.
Edit
Clarify my question and ask it in the following two contexts:
1. import module.function1 where module is a single module.py file which contains function1 and other functions definition and classes definition etc. Is the whole module loaded into memory or just the function1 definition part?
2. import package.function1 where package is a package like numpy where it contains file hierarchy, like Mike Tung described below. Is the whole package loaded into memory, or just the module file that contains the function1 definition, or just the part of that module file which defines function1?
Yes, it does import the whole function. The purpose of including the function is mostly for code style purposes. It makes it easier to understand that you are only using that specific function in the module.
Whether you use
import module
or
import module.function
# this is equivalent to "import module" since you will still have to type
# "module.function()" to use the function. See next answer for correct syntax
or
from module import function
has little impact on memory/performance.
Let's say you have the following structure
app/
├── foo/
│ ├── __init__.py
│ ├── foo1.py
│ └── foo2.py
├── bar/
│ ├── __init__.py
│ └── bar1.py
└── app.py
When you say in app.py
import foo
you are saying import all the py files under foo for use in app.py
when you say:
import foo.foo1
you are saying I only want the contents of foo1.py
When you say:
from foo.foo2 import *
you are saying take all the stuff in foo2 and dump it in to the same namespace as app.py.
In scenario 1 you would have to qualify all your calls extremely specifically.
foo.foo1.function()
In scenario 2
foo1.function()
In scenario 3
function()
Ideally you would be using scenario 2 as it is a nice middle ground and helps to prevent namespace pollution.
import module.function is an error, actually. You can only import submodules, not functions, with that syntax.
from module import function is not an error. from module import function would execute the entire module, since the function may depend in arbitrarily complex ways on the other functions in the module or arbitrary setup executed by the module.
This post indicates that the entire module is still imported even if you are only using a small part of it.

Conveniently import several classes from modules in a Python package

I'm currently creating a framework for a syntax tree. I have a folder/package syntax which contains one syntax tree element which is a class in each file, the structure looks then like:
syntax/List.py -> contains class List
syntax/Block.py -> contains class Block
syntax/Statement.py -> contains class Statement
Now I'd like to import the folder into my source file in a way that I can access the classes like
block = syntax.Block()
Is that possible at all? So far, I always ended up that I need syntax.Block.Block() which is not very nice...
Project structure
syntax
├── Block.py
├── __init__.py
The class
# syntax/Block.py (this file really ought to be lowercase, leave PascalCase to class names)
class Block(object):
pass
Imports in __init__
# syntax/__init__.py
from .Block import Block # Relative import with .
Using the package
In [5]: import syntax
In [6]: b = syntax.Block()
In [7]: b
Out[7]: <syntax.Block.Block at 0x108dcb990>
Alternative if you are open to some re-organization
Unlike languages that require us to put a single class into a file with same name (class Block inside file Block.py), Python is pretty flexible about this.
You can actually put many classes in syntax.py and import syntax alone, then access syntax.Block (no imports in __init__.py would be required for this)
# syntax.py
class Block(object):
pass
class List(object):
pass
Then can use as follows
import syntax
b = syntax.Block()
l = syntax.List()
The most readable way to deal with that is to do your imports into the __init__.py file
Example :
# syntax/__init__.py
from syntax.List import List
from syntax.Block import Block
from syntax.Statement import Statement
# in your main file
from syntax import List
import syntax
b = syntax.Block()
Note: you can also use the relative import syntax in your __init__.py file (for example from .List import List)
When you do an import, you define a variable. This variable is containing your imported variable, constant, function, class or whatever you want.
If you do from .List import List into your __init__.py file, you are defining the variable List into your __init__.py file refering to the class syntax.List.List.
So when you are trying you write from syntax import List you are trying to import the variable List from your __init__.py file, which point to the syntax.List.List.
from syntax import List
from syntax.List import List as OriginList
List is OriginList # True

How to structure modules to avoid things like "import module.module.module"

I have a module structured as follows:
/module
__init__.py
/submod_1
__init__.py
submod_1_class.py
/submod_2
__init__.py
submod_2_class.py
but I find it incredibly annoying to have to import a class within submod_1_class.py with:
from module.submod_1.submod_1_class import my_class
What I would prefer to be able to type is:
from module import my_class
I have browsed through the site-packages folder and looked through popular modules like numpy, but I haven't been able to figure out how, for example:
import numpy
a = numpy.array([1,2,3,4,5])
can be used when the definition of numpy array objects is buried deep within several subfolders of the numpy package.
You can use __init__.py files to define what can be imported from a given module. A very simple addition to your structure, for example, would draw up Class from submod_1_class such that external users can simply from module import Class.
/module
__init__.py
from submod_1 import Class
/submod_1
__init__.py
from submod_1_class import Class
submod_1_class.py
/submod_2
submod_2_class.py
In numpy, for example, the top-level __init__.py contains a line that reads:
from .core import *
This means everything defined within /core/__init__.py is available externally directly in the numpy namespace, even though it may actually be buried deep in some complex structure.

Categories