I am having 2 Python files in same directory. one.py and two.py containing classes First and Second respectively. I want import classes and inherit each other and use methods defined in each other.
one.py
from two import Second
class First(Second):
def first(self):
print "first"
two.py
from one import First
class Second(First):
def second(self):
print "second"
while compiling I am getting following error. Is there any way I can overcome this. Please suggest alternative methods also.
Traceback (most recent call last):
File "C:\Users\uvijayac\Desktop\New folder\two.py", line 1, in <module>
from one import First
File "C:\Users\uvijayac\Desktop\New folder\one.py", line 1, in <module>
from two import Second
File "C:\Users\uvijayac\Desktop\New folder\two.py", line 1, in <module>
from one import First
ImportError: cannot import name First
The actual problem you're encountering is that you're trying to do a circular import, which has nothing to do with your circular inheritance. (There's plenty of material on SO on how to avoid that.)
However, note that circular inheritance is also not possible, as a class is only available for subclassing once it's defined, and its definition includes being subclassed from the other class, which therefore also needs to already be defined, which requires... you get the point - you can't have circular inheritance.
Related
Well. I have a main file with a class in it. I have another file, where i wanna store functions (for the sake of simplicity), which use functions of that class. And I wanna import the second file into the first one, so i can use those functions in main file. And that's where I encountered a problem.
If I'm just importing the second file into the first one, I have an error which says that in second file the class is not defined.
If I'm importing the first file into the second one AND the second one into the first one, I have an error in main file, which says that function I defined in second one doesn't exist.
That's the simpliest variant I can get. File 1:
import random
import Test2
class randoms():
def __init__(self):
pass
def random_shit():
a=random.randrange(19)
return a
WTF= randoms()
Test2.printer()
File 2:
import Test
def printer():
print(Test.WTF.random_shit())
First off some python customs: usually classes are defined with capital letters:
class Randoms():
pass
The problem is in file 2 and the fix will fix both errors for both files you define the object WTF in file 1 and then use it in a function. Basically you are using a variable which doesn’t exist inside the function. What you should do is initialize the object WTF inside the function you would like to use:
def printer():
WTF = Test.randoms()
print(WTF.random_shit())
You can remove the initialization inside the file 1.
Hope this helps.
When we use from <module/package> import *, none of the names that start with a _ will be imported unless the module’s/package’s __all__ list explicitly contains them.
Is this not applicable to variables and functions of a class?
From the below programs, it seems it's not applicable to variables and function inside a class.
_bar and _check_func both are executed in test_import.py. However, _test_func() throws an error for having leading underscore. Am I missing anything here?
test_var.py
class test:
def __init__(self):
self._bar=15
def test_mod(self):
print("this is test mod function")
def _check_func(self):
print("this is _check_func function")
def _test_func():
print("this is test function var 2")
test_import.py
from test_var import *
p1=test()
print(p1._bar)
p1.test_mod()
p1._check_func()
_test_func()
Output:
15
this is test mod function
this is _check_func function
Traceback (most recent call last):
File "test_import.py", line 8, in <module>
_test_func()
NameError: name '_test_func' is not defined
The underscore rule is imposed by the importer when it sees from test_var import *. In fact, the functions are still in the module namespace and you can still use them:
import test_var
test_var._test_func()
You don't import class methods, just classes so the underscore rule isn't applied. p1._check_func() works for the same reason that test_var._test_func() works: You addressed the variable in its namespace.
You imported test and are accessing its members (with or without underscores) through that namespace (in your example, through the instantiated object p1). test is what you import, test._bar is only accessible through test and is not among the imported symbols.
(There are many similar and more generic questions, been trying the solutions from them after reading through them, can't get them working so asking here as a more situation-specific version of what I'm seeing)
I think I am really miss-understanding how Python does OOP due to my more C#/C++ background. So here's what I'm trying to do right this moment.
I'm starting with two modules to set up the rest of my project, partially as a sanity-check and proof-of-concept. One module logs things to a file as I go while also storing data from multiple modules (to eventually package them all and dump them on request) Doing all this in PyCharm and mentioning the error warnings it suggests by the way, and using Python 2.7
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter():
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__builtin__.mylogger = LogHelpers
Module 2:
src\ULTs\myULTs.py
mylogger.myLog.classEnter()
(both the modules and the root src\ have an empty init.py file in them)
So according to the totally awesome response here ( Python - Visibility of global variables in imported modules ) at this stage this should be working, but 'mylogger' becomes an 'unresolved reference'
So that was one approach. I also tried the more straight forward global one ( Python: How to make a cross-module variable? )
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
mylogger.myLog.classEnter()
This version gets a "parameter 'self' unfilled" error on the classEnter, which various reports seem to indicate means that mylogger is un-initialized (misleading error code but that's what it seems to mean)
And then I tried this..
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
def someFunction(self):
global mylogger
mylogger.myLog.classEnter()
And this version gets the 'Global variable is undefined at the module level' error when I hover of global mylogger.
Then there is the idea of each other module tracking its own instance of a class apparently, if I end up having to I can go with that method and coordinate them.. but that's kind of a hack considering what I'm trying to do.
That's kind of where I'm at, that's the gist of what I'm trying to do... I'm reading through as many similar questions as I can but all of them seem to come back to these kinda of solutions (which don't seem to be working) or saying 'don't do that' (which is generally good advice but I'm not really grocking the preferred Pythony way of keeping multiple ongoing non-static classes organized for a large project - other than shoving them all in one directory)
Thoughts? (How badly am I mangling Python here?)
[EDIT] Based on feedback tried a mini version that eliminated the inner classes completely:
Ok, so did a local mini-class based on what you said:
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self):
self.testVar += 1
myClass = testClass()
Set it up via init.py
__all__ = [myClass]
from .logHelpers import myClass
Went to other module and
from helpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar()
Ran it directly instead of looking at PyCharm, no Global anything.. NameError: name 'myClass is not defined
So still at square one :( (and still need to store state)
[EDIT] Adding Traceback:
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module> module = loadSource(a[0])
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource module = imp.load_source(moduleName, fileName)
File "C:\[...mylocation...]\py\src\ULTs\LogHelpers_ULT.py", line 3, in <module> from helpers import myClass
File "C:\[...mylocation...]\py\src\helpers\__init__.py", line 7, in <module>
__all__ = [myClass]
NameError: name 'myClass' is not defined
============================================================================
kk, I got it working with the miniclass. I don't know why the other approach / approaches was not working, but this seemed to fix things.
(Resources: http://docs.python-guide.org/en/latest/writing/structure/ , http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html )
**logHelpers.py**
[... some static logging functionality ...]
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self, source):
self.testVar += 1
mylogger.myLog.info(source + " called, new val: " + str(self.testVar))
myClass = testClass()
**test_LogHelpers_ULT.py**
import unittest
from helpers.logHelpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar("LogHelpers")
For some reason skipping the
init.py
(and leaving it blank) and going for the explicit importation worked. It also maintained state - I created a duplicate of the test file and my log output correctly had '3' for the first file to call the helper, and '4' for the second file to call the helper.
Thanks Daniel Roseman for the help and suggestions, they had me look a bit more in the right direction. If you can spot why the previous stuff wasn't working it would be much appreciate just to add to my understanding of this language, but I'm gonna go ahead and mark your answer as 'Answered' since it had some very useful feedback.
Before I start, note that the PyCharm warnings are not actual Python errors: if you ran your code, you would probably get more useful feedback (remember static analysis of a dynamic language like Python can only get you so far, many things can't be resolved until you actually run the code).
Firstly, it's really not clear why you have nested classes here. The outer class seems completely useless; you should remove it.
The reason for the error message about "self" is that you have defined an instance method, which can only be called on an instance of log. You could make mylogger (absolutely no need for the double-underscore prefix) an instance: mylogger = log() - and then import that, or import the class and instantiate it where it is used.
So in your first snippet, the error message is quite clear: you have not defined mylogger. Using my recommendation above, you can do from helpers import mylogger and then directly call mylogger.classEnter().
Finally, I can't see what that global statement is doing in someFunction. There's no need to declare a name as global unless you plan to reassign it within your scope and have that reassignment reflected in the global scope. You're not doing that here, so no need for global.
By the way, you should also question whether you even need the inner log class. Generally speaking, classes are only useful when you need to store some kind of state in the object. Here, as your docstring says, you have a collection of utility methods. So why put them in a class? Just make them top-level functions inside the logHelpers module (incidentally, Python style prefers lower_case_with_underscore for module names, so it should be "log_helpers.py").
I am working my way through the excellent 'Python The Hard Way' and copied the following code into a file called mystuff.py:
class MyStuff(object):
def __init__(self):
self.tangerine = "And now a thousand years between"
def apple(self):
print "I AM CLASSY APPLES!"
In terminal:
import mystuff
thing = MyStuff()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'MyStuff' is not defined
This has been happening repeatedly with other simple classes today. Can someone tell me what I am doing wrong?
You probably want thing = mystuff.MyStuff() (assuming mystuff is the name of the file where the class MyStuff resides).
The issue here is with how python handles namespaces. You bring something into the current namespace by importing it, but there's a lot of flexibility in how you merge the namespaces from one file into another. For example,
import mystuff
brings everything from the mystuff (module/file level) namespace into your current namespace, but to access it, you need mystuff.function_or_class_or_data. If you don't want to type mystuff all the time, you can change the name you use to reference it in the current module (file):
import mystuff as ms
now, you can acess MyStuff by:
thing = ms.MyStuff()
And (almost) finally, there's the from mystuff import MyStuff. In this form, you bring MyStuff directly into your namespace, but nothing else from mystuff comes into your namespace.
Last, (and this one isn't recommended) from mystuff import *. This works the same as the previous one, but it also grabs everything else in the mystuff file and imports that too.
You are importing the module in to your local namespace, but not the class. If you want to use the class with your current import, you need:
thing = mystuff.MyStuff()
If you want to use the declaration you have, you need:
from mystuff import MyStuff
Ok,I guess u got what u need.But here is what's going on with it
import mystuff
#with this type of import all the names in the `mystuff` module's namespace are not copied into current modules namespace.
So you need to use mystuff.MyStuff()
use from mystuff import * to copy names in the mystuff module's namespace to current module's namespace.Now you can directly use thing=MyStuff()
class UserDict:
def __init__(self, dict=None):
self.data = {}
if dict is not None: self.update(dict)
I created a file "abc.py" and put above in it.
>>> import abc
>>> d = abc.UserDict()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'UserDict'
Most certainly you are importing the Python abc module for abstract base classes instead of your own abc.py. Better choose a different name for your module.
Edit: Of course it is possible to have your own module with the same name as a built-in module and to import it. You have to make sure that your module is in the interpreter's working directory or set the Python path correctly. But it is much easier to avoid the name clash -- in particular in this case, where you presumably don't care about the module's name anyway.