How to use a python module on inherited class - python

I have a base class A in base.py:
import module1
class A:
def test(self):
module1.sample("test")
Then in new.py I created a new class B which inherits A and override test method:
from base import A
class B(A):
def test(self):
module1.sample("test")
print("Testing...")
The problem is that the module1 is no longer available in new.py. Is there any options that I do not need to import module1 again in new.py?

One not recommended way to achieve what you want is to use __builtins__. Add the following line to base.py.
__builtins__['module1'] = module1
Then module1 is no longer undefined from new.py. It is definitely defined in __builtins__.
Again, it is not recommended, however, good to understand how Python works. You would better import module1 from new.py as well.
import module1
from base import A
...

Related

Import a Python module without adding it to the local namespace

What I'd like to do
I'd like to import a Python module without adding it to the local namespace.
In other words, I'd like to do this:
import foo
del foo
Is there a cleaner way to do this?
Why I want to do it
The short version is that importing foo has a side effect that I want, but I don't really want it in my namespace afterwards.
The long version is that I have a base class that uses __init_subclass__() to register its subclasses. So base.py looks like this:
class Base:
_subclasses = {}
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls._subclasses[cls.__name__] = cls
#classmethod
def get_subclass(cls, class_name):
return cls._subclasses[class_name]
And its subclasses are defined in separate files, e.g. foo_a.py:
from base import Base
class FooA(Base):
pass
and so on.
The net effect here is that if I do
from base import Base
print(f"Before import: {Base._subclasses}")
import foo_a
import foo_b
print(f"After import: {Base._subclasses}")
then I would see
Before import: {}
After import: {'FooA': <class 'foo_a.FooA'>, 'FooB': <class 'foo_b.FooB'>}
So I needed to import these modules for the side effect of adding a reference to Base._subclasses, but now that that's done, I don't need them in my namespace anymore because I'm just going to be using Base.get_subclass().
I know I could just leave them there, but this is going into an __init__.py so I'd like to tidy up that namespace.
del works perfectly fine, I'm just wondering if there's a cleaner or more idiomatic way to do this.
If you want to import a module without assigning the module object to a variable, you can use importlib.import_module and ignore the return value:
import importlib
importlib.import_module("foo")
Note that using importlib.import_module is preferable over using the __import__ builtin directly for simple usages. See the builtin documenation for details.

Checking the child / parent relationship of a class while preventing circular import / circular dependency

I have these modules:
# module 1
from abc import ABC
from module3 import AnotherClass
class Parent(ABC):
#classmethod
def func1(cls):
other_param = "foo"
AnotherClass.some_func(cls, other_param)
# module 2
from module1 import Parent
from module3 import AnotherClass
class Child1(Parent):
pass
class Child2(Parent):
pass
# module 3
from module1 import Parent # only for checking if the object is a subclass of Parent
class AnotherClass(object):
#classmethod
def some_func(cls, child_cls, other_param):
assert issubclass(child_cls, Parent)
# do other stuff
now if I do this:
c1 = Child1()
c1.func1()
I rightfully get an ImportError complaining from a circular import as follows:
ImportError: cannot import name 'Parent' from partially initialized
module 'module1' (most likely due to a circular import)
Actually AnotherClass does not depend on Parent or any of the Child classes, I'm importing the Parent only for checking if the passed class is a subclass of Parent, in this row:
assert issubclass(child_cls, Parent)
Now, I can defer importing of the Parent like this:
# module 3
class AnotherClass(object):
#classmethod
def some_func(cls, child_cls, other_param):
from module1 import Parent # only for type checking
assert issubclass(child_cls, Parent)
# do other stuff
And it works like a charm. But for some reason (unknown to me) I feel uncomfortable doing it this way.
Now my question is, can I sleep with peace deferring the import like that, or would it bite me in some way later on down the road?
If yes, how would you suggest I do the this parent / child relationship check at AnotherClass.some_func()?
P.S.
Before anyone brings it up, I know this topic of circular dependencies has been asked and answered many many times (such as this one), but I'm asking if this specific solution is feasible and problem-free in the long run.
There's nothing inherently wrong with your current solution. In this case you could also solve it like this though, which is imo a bit cleaner:
import module1
class AnotherClass(object):
#classmethod
def some_func(cls, child_cls, other_param):
assert issubclass(child_cls, module1.Parent)
First of all, you are not really doing "type checking" there, asserts are a completely different thing, since they are actually processed at run time.
I think you'd be best off using actual type-hints, and by using them there's a really simple and idiomatic way to avoid issues with circular imports:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from module1 import Parent
class AnotherClass: # No need to inherit from `object` in Python 3.
#classmethod
def some_func(cls, child_cls: "Parent", other_param):
...

How to make imports in Python

my problem is following, I have an application in the following hierarchy:
main.py
package/__init__.py
package/MyClass.py
Clearly there is a package named "package". In the MyClass.py there is a class definition.
Now, while im in "main.py" file, to get the class instance i have to do:
package.MyClass.MyClass()
in order to create and instance of that class.
Now I want to be able to write only
package.MyClass()
To instantiate a class. How do I do this? I saw many apis do it this way, is there some trick to do it?
Add this in __init__.py:
from .MyClass import Myclass
Then, in main.py:
import package
package.MyClass()
Or again:
from package import MyClass
MyClass()
Make __init__.py:
from .package import MyClass

Correct way to import a class from a package in Python

I have a class like this in package a:
class A:
#staticmethod
def method(param1, param2):
...
return something
And in a python file:
from a import A
print(A.A.method(p1,p2))
What is wrong in my definitions? I think isn't correct to call a static method by `Class.Class.method'.
Screenshots with errors:
[EDIT after question was updated with picture]
So your top-level app is called a you can see this in the picture just under "Information" on the left in the picture. Then you have a module called A, which you can see the file A.py just under the folder a. This module A has the class called A
so when you do from a import A you are importing the file A.py
That file has a class A() which has def method(p1, p2)
You say A.A.method() is working... and that would be correct
It now becomes
from a import A
print(A.A.method(p1,p2)
Alternatively
import a
print(a.A.A.method(p1,p2)
Or
from a.A import A
print(A.method(p1, p2)
My advice: start using some more descriptive names, not a for top
level package and A for module and A for class

How does Python handle imported subclasses?

I am working on a project that requires me to build several classes and subclasses in one file, and use them in a second file. I would like to ask how Python handles importing the first file into the second.
For instance, if i have a file my_classes.py:
class Myclass(object):
pass
class Mysubclass(myclass):
pass
will using the following code work:
from my_classes import Myclass
print Mysubclass
(where the print command is just an example of using Mysubclass), or do I need to import Mysubclass explicitly?
Thanks in advance!
This won't work. Python import statement doesn't care about subclasses. Actually, it doesn't care about anything. It does precisely what you tell it to do. "Explicit is better than implicit" is a popular saying in Python circles.
Here:
from my_classes import Myclass
You told Python to import only Myclass.
This will import both classes:
from my_classes import Myclass, Mysubclass
You can read how Python import works here.
Your subclass will not be available if you do it like this. You must import every object by itself.
Here a quick example
test_class.py
class MyClass(object):
def init(self):
print self.class
class MySubClass(MyClass):
def __init__(self):
print self.__class__
test_class_import.py
from test_class import MyClass
MyClass()
MySubClass()
##output##
<class 'test_class.MyClass'>
Traceback (most recent call last):
File "test_class2.py", line 4, in <module>
MySubClass()
NameError: name 'MySubClass' is not defined
but
from test_class import MyClass, MySubClass
MyClass()
MySubClass()
##output##
<class 'test_class.MyClass'>
<class 'test_class.MySubClass'>
Every module has a namespace.
A namespace is a mapping from variable names to values (Python objects).
The statement
import my_classes
makes the my_classes namespace accessible from the current module by placing the variable name my_classes in the current module's namespace. You can then access values from my_classes with the syntax
my_classes.variable
So, for example:
import my_classes
print my_classes.Mysubclass
print my_classes.MyClass
If that is too much typing, I suggest
import my_classes as MC
print MC.Mysubclass
print MC.MyClass
you could also do
from my_classes import Mysubclass, MyClass
but this form of import is discouraged by some Python experts.
from my_classes import Mysubclass, MyClass
loads the entire module my_class but only
places the variable names Mysubclass and MyClass in the current module's namespace. They point to the same values as do the variables of the same name in the my_classes namespace. You don't get access to anything else from the my_class module's namespace.

Categories

Resources