Importing a class by referring to it with a variable? - python

Edit: This question was on the assumption that I could import parts of modules without importing the whole module. It turns out that isn't the case so I decided to just import the whole module with from ex45_extras import * anyway. That makes this question pointless, but I decided to not delete this question so that some other beginner with the same question can come here and find out the sad truth: You can't import modules as parts anyways
The following is the original question:
I'm a beginner so sry for the noob question. I want to call specific classes from a module with a variable. I don't want to call the whole module. And I need to do this using this class Nav() to control which classes are being imported. Is there a way to do this? Or is there a better solution?
class Nav():
def __init__(self):
print("This is class Nav")
def play(self):
current_scene_name = "A()" # this is where the variable is defined
from ex45_extras import current_scene_name # <- this is the one
x = Nav()
x.play()
Currently it's raising this error:
This is class Nav
Traceback (most recent call last):
File "D:\Programming\Python\LPTHW_Exs\ex45\test.py", line 11, in <module>
x.play()
File "D:\Programming\Python\LPTHW_Exs\ex45\test.py", line 7, in play
from ex45_extras import current_scene_name
ImportError: cannot import name 'current_scene_name' from 'ex45_extras' (D:\Programming\Python\LPTHW_Exs\ex45\ex45_extras.py)

Class names don't have a trailing () suffix — that's how you create an instance of one (i.e. by calling it).
Anyhow, if ex45_extras.py defines a class named A:
class A:
pass
Then you could import the class via a string containing its name, and then create an instance of it as shown below:
class Nav():
def __init__(self):
print("This is class Nav")
def play(self):
import ex45_extras
current_scene_name = 'A' # this is where the variable is defined
class_ = getattr(ex45_extras, current_scene_name) # Get class.
instance = class_() # Create instance of class.
print(f'{instance=}') # -> instance=<ex45_extras.A object at 0x010D4838>
x = Nav()
x.play()

guess it's because you're trying to import an string "A()" instead of a class A()

Related

Python, define global variable in a class and import this class for main script,but that global variable is not defined

I have a basic.py file under a specific folder which defined a class:
class test_function:
def loop_unit(self,str):
global test_list
test_list.append(str)
I have another main.py which have following code
from folder import basic
test_list=[]
object=basic.test_function()
object.loop_unit('teststr')
print(test_list)
it will give an error says
name 'test_list' is not defined(it trackback to test_list.append(str) )
I actually defined global variable in the function, and I defined it at the start of the main code, why it still said this is not defined?
You defined main.test_list; test_function.loop_unit wants basic.test_list.
from folder import basic
basic.test_list = []
object = basic.test_function()
object.loop_unit('teststr')
print(basic.test_list)
Try to do this in your class definition:
class test_function:
def __init__(self):
self.test_list = []
def loop_unit(self,str):
sel.test_list.append(str)
from folder import basic
#test_list=[] --remove this line
object=basic.test_function()
object.loop_unit('teststr')
#print(test_list) ---remove this line but add this:
print(object.test_list)
Try and tell me if it works.

How to import a class from another file which is importing first class for [duplicate]

I want to separate code in different class and put them to different files. However those class are dependent on each other.
main.py:
from lib import A, B
def main():
a = A()
b = B()
a.hello()
b.hello()
if __name__ == '__main__':
main()
lib/_init_.py:
from a import A
from b import B
lib/a.py:
import lib.B
class A():
def __init__(self):
print "A"
def hello(self):
print "hello A"
b = B()
lib/b.py:
import lib.A
class B():
def __init__(self):
print "B"
def hello(self):
print "hello B"
a = A()
Is it possible to do that in Python?
EDIT:
I get this error message:
pydev debugger: starting
Traceback (most recent call last):
File "eclipse-python/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1397, in <module>
debugger.run(setup['file'], None, None)
File "eclipse-python/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1090, in run
pydev_imports.execfile(file, globals, locals) #execute the script
File "main.py", line 2, in <module>
from lib import A, B
File "lib/__init__.py", line 1, in <module>
from a import A
File "lib/a.py", line 1, in <module>
import lib.B
ImportError: No module named B
Instead of importing the modules on top, you could import the other module within the hello function.
class B():
def __init__(self):
print "B"
def hello(self):
from lib import A
print "hello B"
a = A()
When you have two classes depending on each other usually means that either they really belong to the same module or that you have a too tight coupling that should be resolved using dependency injection.
Now there are indeed a couple corner cases where importing from within the function is the "least worst" solution but that's still something you should avoid as much as possible.
Your main problem is that you're trying to import a class, but using syntax that only works to import a module. Specifically, import lib.A is never going to work if A is a class defined in module lib.a (and imported into the top-level namespace of lib).
What I suggest is that you avoid using the from _ import _ syntax unless you really need it. That makes the dependencies much easier to resolve:
lib/a.py:
import lib.b # note, we're not importing the class B, just the module b!
class A():
def foo(self):
return lib.b.B() # use the class later, with a qualified name
lib/b.py:
import lib.a # again, just import the module, not the class
class B():
def foo(self):
return lib.a.A() # use another qualified name reference
lib/__init__.py:
from a import A # these imports are fine, since the sub-modules don't rely on them
from b import B # they can be the public API for the A and B classes
You could also use relative module imports if you don't want a and b to be dependent on the name of their package lib.
This is sure to work because neither class A or B actually requires the other to exist yet in order to be defined. It's only after they're imported that instances of A need to know about the class B (and vise versa).
If one of the classes inherited from the other, or otherwise used an instance of the other at top level, you'd need to be more careful about which module was loaded up first, or it might still break.
If you want to import it only once you can import it in the constructor of the class and make the variable global:
class B():
def __init__(self):
global A
from lib import A
print "B"
def hello(self):
print "hello B"
a = A()
This would import A into a global variable and make it accessible form within the module.

Global name not defined error in Python

I am implementing my first class in Python and am struggling to make it work. I started with a very simple example:
#!/usr/bin/env python
"""
"""
import fetcher as fetcher
import fetchQueue as fetchQueue
def __init__(self, seed = "a string"):
self.seed = seed
myFetchQueue = fetchQueue.FETCHQueue()
def test(self):
print "test"
myFetchQueue.push(seed)
myFetchQueue.pop()
#Entrance of this script, just like the "main()" function in C.
if __name__ == "__main__":
import sys
myGraphBuilder = GRAPHBuilder()
myGraphBuilder.test()
and this class should call a method of another class I defined in a very similar way.
#!/usr/bin/env python
"""
"""
from collections import defaultdict
from Queue import Queue
class FETCHQueue():
linkQueue = Queue(maxsize=0)
visitedLinkDictionary = defaultdict(int)
#Push a list of links in the QUEUE
def push( linkList ):
print linkList
#Pop the next link to be fetched
def pop():
print "pop"
However when I run the code I get this output:
test Traceback (most recent call last): File "buildWebGraph.py", line 40, in <module>
myGraphBuilder.test() File "buildWebGraph.py", line 32, in test
myFetchQueue.push(seed) NameError: global name 'myFetchQueue' is not defined
So I guess that the construction of the object of class GRAPHBuilder and FETCHQueue is working, otherwise I would get an error before the string test gets outputed, but something else is going wrong. Can you help me?
def __init__(self, seed = "a string"):
self.seed = seed
myFetchQueue = fetchQueue.FETCHQueue()
Here, myFetchQueue is a local variable to the __init__ function. So, it will not available to other functions in the class. You might want to add it to the current instance, like this
self.myFetchQueue = fetchQueue.FETCHQueue()
Same way, when you are accessing it, you have to access it with the corresponding instance, like this
self.myFetchQueue.push(self.seed)
self.myFetchQueue.pop()

how to change a variable from a module inside a module in a module... (confused)

I have a variable in my main module which is changed using another module, but I want to change the variable from my main module through another module. I'm new to programmering, so I actually don't really know how to explain this stuff - sorry if I'm asking a stupid question.
The program's hierarchy looks a bit like this:
Main
---Features
---Pygame_handling
------Features
I use the "Features" module to change a variable in the "Main". I do this simply by getting the defined variable from "Features". But when I change the variable through "Pygame_handling", it is not changed in the "Features" object created in the "Main" module.
Main.py
import Features
class Simulator:
def __init__(self):
self.Features = Features.Methods()
self.variables = self.Features.dictionary
self.PyObject = Pygame_handling.Window()
Pygame_handling.py
import Features
class Window:
def __init__(self):
self.Features = Features.Methods()
dict = {"some":"dict"}
self.Features.monitor_changes(dict)
How are you initializing those classes?
Usually when I need to do something like this I code it like:
py1.py:
class Test(object):
def test_print(self):
print 'Hi!'
TEST = Test()
py2.py:
from py1 import TEST
TEST.test_print()
# Adding new stuff to the TEST initialized class
TEST.new_var = 50
print TEST.new_var
#output: 50
So now you can just use the initialized class from on that module.

Correct use of static methods

I have following simplified class named Password.py in folder1:
import random
CHARS = "ABC"
class PasswordHelper(object):
#staticmethod
def generateChars(length):
return ''.join(random.choice(CHARS) for x in range(length))
Now I have another class TestClass.py in folder2:
sys.path.append('../folder1/')
import Password
class Tester:
def whatever(self):
print Password.generateChars(3)
def main():
x = Tester()
x.whatever()
# call main method
main()
When calling python TestClass.py I get the following error: AttributeError: 'module' object has no attribute 'generateChars'. Both folders are on the same level. Is there a problem with the way I import the class files or with the static method declaration itself?
Python is not Java.
Firstly, there is absolutely no point to either the Tester or the Password classes. If you're not storing state, then don't define a class. Make both whatever and generateChars into normal standalone functions.
However, assuming you're doing this just to learn about Python classes, you have not understood that a class does not equal a module in Python. Since you've imported the Password module, you still need to refer to the PasswordHelper class:
Password.PasswordHelper.generateChars(3)
Alternatively, you can import the PasswordHelper class:
from Password import PasswordHelper
...
PasswordHelper.generateChars(3)
Finally, please follow PEP8 for your module, class and function names.
You defined the function in a class, so you need to reference it with the classname too:
print Password.PasswordHelper.generateChars(3)
Alternatively, move the function out of the class definition, at which point you do not need to use #staticmethod at all:
import random
CHARS = "ABC"
def generateChars(length):
return ''.join(random.choice(CHARS) for x in range(length))
In Python, functions do not have to be part of a class definition.

Categories

Resources