python className not defined NameError - python

I have a class which i need to instantiate in order to call a method that it contains. When I access it from another class it works fine but when i run from terminal it says :
File "myClass.py", line 5, in <module>
class MyClass:
File "myClass.py", line 23, in ToDict
td=MyClass()
NameError: name 'MyClass' is not defined
Pasting the code:
class MyClass:
def convert(self, fl):
xpD = {}
# process some stuff
return xpD
if __name__ == "__main__":
source = sys.argv[1]
td = MyClass()
needed_stuff = td.convert(source)
print(needed_stuff)

The problem is that your if __name__ == "__main__" block is inside of your class definition. This will cause an error, as the code within the if will be run as part of the class being created, before the class been bound to a name.
Here's a simpler example of this error:
class Foo(object):
foo = Foo() # raises NameError because the name Foo isn't bound yet
If you format your code like this (that is, with the if unindented at the top level), it should work correctly:
class MyClass:
def convert(self, fl):
xpD = {}
# process some stuff
return xpD
if __name__ == "__main__":
source = sys.argv[1]
td = MyClass()
needed_stuff = td.convert(source)
print(needed_stuff)

Related

Use a class variable in a class method

After I ran the code below, I got NameError: name 'result' is not defined. I tried to use class variable in a class method. Why does it give me an error?
class Test():
def __init__(self):
self.a=self.test1()
self.result = Test.test2()+Test.test3()
def test1(self):
a=100
return a
result = Test.test3()+100
#classmethod
def test2(cls):
b=200
return b
#staticmethod
def test3():
print("Testing3 is calling ")
c=500+Test.result
return c
Error:
result = Test.test3()+100
File "<ipython-input-29-29d4025016c1>", line 18, in test3
c=500+result
NameError: name 'result' is not defined
At the time the line of code in question is evaluated, result is not a class variable. It's been defined as an instance variable here:
def __init__(self):
self.a=self.test1()
self.result = Test.test2()+Test.test3()
but the line of code that defines Test.result as a class variable:
result = Test.test3()+100
has not yet finished executing at the time that it calls test3(), which itself has a dependency on Test.result.

How to dynamically import the class?

I have four files: main.py, MainClass.py, SigClass.py, and MyClassC.py. The entry is main.py. I rewrite the function function_a of MyClassA in MyClassC, so I need to set SigClass in main.py sig attribute, so MainClass inherits MyclassC and MyclassA in MainClass.py. My code is as follows, which does not inherit the function function_a of MyClassC.
This question explains why the weird class in the middle is used.
I have tried many methods, but I can only achieve my goal in TempClass in the main() space of MainClass.py, but in __main__ of MainClass.py Space can't do it.
How can the TempClass in the main() space be referenced in other files? I really can’t think of a way.
How can I modify the code? Or is there any other way?
The sample code is as follows:
main.py:
from MainClass import SigClass, main
SigClass.sig = "MyClassC"
main()
from MainClass import MainClass
MainClass.function_a()
print(MainClass.property)
MainClass.py:
from time import time
from SigClass import SigClass
import importlib
sig = SigClass.sig
class MyClassA:
sig = '1'
property = 'A'
#classmethod
def function_a(cls):
cls.property = 'A'
class MainClass:
pass
def main():
module_name = SigClass.sig
class_name = SigClass.sig
module_object = importlib.import_module(module_name)
module_class_object = getattr(module_object, class_name)
class TempClass(module_class_object, MyClassA):
pass
global MainClass
MainClass = TempClass
SigClass.py
class SigClass:
sig = 1
MyClassC.py
from MainClass import MyClassA
class MyClassC(MyClassA):
#classmethod
def function_a(cls):
cls.property = 'c'
pass
Thanks to #2e0byo's tips, I think the following code best meets my needs:
Import MyClassC according to SigClass.sig, and SigClass.sig is also the most important part of MainClass.
class BaseClass:
name = None
pass
class SigClass(BaseClass):
name = "SigClass"
sig = 1
class MyClassA(BaseClass):
name = "MyClassA"
property = 'A'
sig = 'a'
#classmethod
def function_a(cls):
pass
class MyClassC(MyClassA):
name = "MyClassC"
property = "C"
sig = 'c'
#classmethod
def function_a(cls):
pass
class ClassCollections(BaseClass):
classes: dict = {}
#classmethod
def add_class(cls, class_to_add: type(BaseClass)):
cls.classes[class_to_add.name] = class_to_add
SigClass.sig = "MyClassC"
ClassCollections.add_class(MyClassA)
ClassCollections.add_class(MyClassC)
class MainClass(SigClass, ClassCollections.classes[SigClass.sig], MyClassA):
pass
print(MainClass.sig)
MyClassC

Python:Error calling class variable in a staticmethod

I am trying to call a class variable within a staticmethod, but when I called I am getting an error "hello" is not defined. any advise ?
class hello:
random1 = []
#staticmethod
def sub(x):
hello.random1.append(x -1)
sub.__func__(2)
if __name__ == "__main__":
print(hello.random1)
hello doesn't exist as a global name until you dedent out of the class definition (at which point the class is created and assigned to the global name hello). Change the code to:
class hello:
random1 = []
#staticmethod
def sub(x):
hello.random1.append(x -1)
hello.sub(2)
so sub is invoked after hello exists, and it will work.

Python namespace and global variable between files

I have 2 differents files. The first one, defines a lot of class:
# File 1:
class Class1:
class Class2:
#...
Those classes uses some variables that are define as global.
# File 1:
class Class1:
def __init__(self, var1):
global glob_variable_1
# Other stuff
class Class2:
#...
In the file 2, I import all the class from the first file and then use them. In this main part of this file, I define the global variables.
# File 2
from File1 import Class1, Class2
if __name__ == '__main__':
global glob_variable_1
glob_variable_1 = 10
# Other stuff
Class1(var1)
I get the error NameError: name 'glob_variable_1' is not defined.. I suppose
it's a problem of namespace and scope, but I don't really understand how it works. Can someone give me a hand? Thanks.
You have two glob_variable_1 names, one in each namespace and you must decide which one to use:
# File 1:
# defined here, outside the class
glob_variable_1 = None
class Class1:
def __init__(self, var1):
global glob_variable_1
glob_variable_1 = 42
# Other stuff
class Class2:
pass
with:
# File 2
from File1 import Class1, Class2
import File1
if __name__ == '__main__':
global glob_variable_1
# Other stuff
var1 = 1234
obj = Class1(var1)
glob_variable_1 = 666
print(glob_variable_1)
print(File1.glob_variable_1)
Gives:
666
42
Far better than using a global variable across modules is to use a function to set/get in a class or a file.

How can I dynamically add a function to an instance in python upon instantiation

If I have a python class which allows for an options parameter upon instantiation, how can I dynamically set a function to it, based upon the value of that options parameter. For example, if I have the code
def hello1():
print(self.name,"says hi")
def hello2():
print(self.name,"says hello")
class A:
def __init__(self, name, opt=0):
if opt == 1:
setattr(self,'hello',hello1)
else:
setattr(self,'hello',hello2)
if __name__ == "__main__":
a1 = A("my")
a2 = A("name",1)
a1.hello()
a2.hello()
I get the traceback error
Traceback (most recent call last):
File "dynamic_classes.py", line 17, in <module>
a1.hello()
File "dynamic_classes.py", line 5, in hello2
print(self.name,"says hello")
NameError: global name 'self' is not defined
Your functions do not define a self parameter, nor will they ever get one.
You need to use methods; you can create these from the functions by treating them as descriptors and explicitly calling .__get__() on them:
def hello1(self):
print(self.name,"says hi")
def hello2(self):
print(self.name,"says hello")
class A:
def __init__(self, name, opt=0):
if opt == 1:
setattr(self, 'hello', hello1.__get__(self, type(self))
else:
setattr(self, 'hello', hello2.__get__(self, type(self)))
Normally, the .__get__() method is called on functions when accessing them on a class (either directly or via an instance). This doesn't happen for functions added directly on an instance however, so you need to do it manually.
You can also use MethodType from types module.
import types
def hello1(self):
print(self.name,"says hi")
def hello2(self):
print(self.name,"says hello")
class A:
def __init__(self, name, opt=0):
self.name = name
if opt == 1:
self.hello = types.MethodType(hello1, self)
else:
self.hello = types.MethodType(hello2, self)
A('a').hello() # ('a', 'says hello')
A('a', 1).hello() # ('a', 'says hi')

Categories

Resources