Initialise static variable by calling function python3 [duplicate] - python

I wanted to define a class as follows:
class ConfigManager:
#classmethod
def load_config(cls):
# do some complex stuff to load something
return config
__CONFIG = ConfigManager.load_config()
#classmethod
def get_config(cls):
return cls.__CONFIG
And then when I run the following code, it reports a NameError:
x = ConfigManager.get_config()
Traceback (most recent call last):
File "test.py", line 1, in <module>
class ConfigManager:
File "test.py", line 7, in ConfigManager
__CONFIG = ConfigManager.load_config()
NameError: name 'ConfigManager' is not defined
Why does this error occur? Is it because Python code is executed by interpretation and when it goes to line 7, class ConfigManager is not yet finished to be defined?

A class object only exists by its name after the class body and all class decorators are evaluated. What that means is that you cannot use the name ConfigManager inside the ConfigManager body itself. This also includes any function or method you call before the class is completed.
While building the class body, you can refer to names previously defined in the class body and names previously defined outside of the class body.
external_name = 'External'
class Demo:
internal_name = 'Internal'
print('Body see', external_name, internal_name)
# throws an error
print('Body does not see', late_internal_name, late_external_name)
late_internal_name = 'LateInternal'
late_external_name = 'LateExternal'
This means you can define a function to load your configuration as long as it does not need the class object. Note that even when defined inside the class, this is not a (class-) method by the time you access it.
class ConfigManager:
# not a method - does not receive cls/self
def load_config():
# do some complex stuff to load something
return {}
# call helper as a regular function
__CONFIG = load_config()
# clean up helper since it is not a proper method
del load_config
#classmethod
def get_config(cls):
return cls.__CONFIG
Alternatively, you can lazily load the config if needed.
class ConfigManager:
_CONFIG = None
#classmethod
def _load_config(cls):
# do some complex stuff to load something
return {}
#classmethod
def get_config(cls):
if cls._CONFIG is None:
cls._CONFIG = cls._load_config()
return cls._CONFIG

Related

Why I got TypeError if calling staticmethod without class-body?

Why it happens? is this "binding behavior”?
using staticmethod in class body
>>> class Test:
#staticmethod
def test(msg="asd"):
print(msg)
>>> test = Test()
>>> test.test()
asd
but when I using it without, got error:
>>> #staticmethod
def test(msg=""):
print(msg)
>>> test
<staticmethod object at 0x10dde9be0>
>>> test()
Traceback (most recent call last):
File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
exec(exp, global_vars, local_vars)
File "<input>", line 1, in <module>
TypeError: 'staticmethod' object is not callable
A static method is a method that is bound to a class but does not require the class instance to function.
For example, you may have a class built around a file type to retrieve raw data from a source file and pass it to a lexer, your constructor could have you pass in the raw file however you may want another function to open the file, validate it and retrieve the data. In this case, you could use a static function within the class as the function is related to the class but doesn't require the class to function (in this case it would return the actual class).
A code example:
class PythonFile:
def __init__(self, raw_data):
self._raw_data = raw_data
self._lexer = None
#staticmethod
def open(fp):
with open(fp, "r") as rFile:
data = rFile.read()
# validate, etc...
return PythonFile(data)
def lex(self):
self._lexer = PythonLex(self._raw_data)
return self._lexer.get_master_block_array()
# etc, etc...
python_file = PythonFile.open("some\\path.py")
print(python_file.lex())
ItzTheDodo.
Use a standalone function.
def test(msg=""):
print(msg)

user defined class serialization and deserialization in python

I am very new to python : I want to serialize and deserialize my custom object in python. Please guide me on the same. I have a sample class :
import pickle
import json
class MyClass():
variable = "blah"
num = 10
def function(self):
print("this is a message inside the class.")
def get_variable():
return variable
def get_num():
return num
def main():
myObj = MyClass()
with open('/opt/infi/deeMyObj.txt', 'w') as output:
pickle.dump(myObj, output,pickle.HIGHEST_PROTOCOL)
with open('/opt/infi/deeMyObj.txt', 'r') as input:
myObjread = pickle.load(input)
print myObjread.get_variable()
print myObjread.get_num()
main()
I am getting following error :
Traceback (most recent call last):
File "sample.py", line 30, in
main()
File "sample.py", line 27, in main
print myObjread.get_variable()
TypeError: get_variable() takes no arguments (1 given)
Main intention is to read the object back.
To expand on jasonharper's comment, your get_variable and get_num methods aren't referring to the class's member variables. They should take the object as their first argument, e.g.
class MyClass:
...
def get_variable(self):
return self.variable
I think your serialization code is OK, but I might be wrong.
(Aside)
This is a bit off-topic, but another thing to note: when you define variables directly within the class block, they're defined on the class, not on objects of that class. That happens to work out in this case, since Python will look for a class-level variable of the same name if it can't find one on the object. However, if you store, say, a list in one of them and start modifying it, you'd end up sharing it between objects, which is probably not what you want. Instead you want to define them on in an __init__ method:
class MyClass:
def __init__(self):
self.variable = "blah"

python unittest is not allowing object attribute reference

So I am trying to setup a unittest for a threaded class in python
The class looks like this:
#Singleton
class EventManager(threading.Thread):
def __init__(self):
self.__eventDict = {}
self.__eventDictLock = threading.Lock()
self.__eventQueue = Queue()
self.__subscriberList = []
threading.Thread.__init__(self)
def run(self):
while(True):
if self.__eventQueue.qsize() > 0:
self.__runEvent()
else:
time.sleep(1)
My unittest looks like this:
eventManager = EventManager.Instance()
eventManager.start()
class EventManagerTest(unittest.TestCase):
#pre-test initialization
def setUp(self):
pass
#post-test destruction
def tearDown(self):
pass
def testRegisterEvent(self):
global eventManager
logger.debug("Entering testRegisterEvent()")
eventManager.registerEvent("MyEvent")
logger.debug("testRegisterEvent() appears to have successfully registered")
self.assertIn("MyEvent", eventManager.__subscriberList)
self.assertFalse( eventManager.__eventDict["MyEvent"])
And I'm getting an error like this:
ERROR: testRegisterEvent (__main__.EventManagerTest)
Traceback (most recent call last):
File "EventManager_Test.py", line 59, in testRegisterEvent
self.assertIn("MyEvent", eventManager.__eventDict)
AttributeError: 'EventManager' object has no attribute '\_EventManagerTest\__eventDict'
Where is the _EventManagerTest__eventDict attribute coming from? That is not the attribute I'm calling and it's preventing me from running a unit test.
As __eventDict starts with two underscore, it is a private attribute, therefore its name is “mangled”, that's why the name changed.
The problem is not related to unittest, it is just that you are trying to access a private attribute.
To solve your problem, remove one (or two) underscore(s) at the beginning of the name of __eventDict to make it protected (or public).

Python: how to automatically create an instance in another class

In writing a Python (2.5) program, I tried to create a class and, in its __init__ function, automatically create an instance of another class with its name as an argument to the __init__ function, something like this:
class Class1:
def __init__(self,attribute):
self.attribute1=attribute
class Class2:
def __init__(self,instanceName):
#any of Class2's attributes
exec instanceName + '=Class1('attribute1')'
# this should produce an instance of Class1 whose name is instanceName
But when I make an instance of Class2, instance=Class2('instance2'), and try to get attribute1 of instance2 (which should have been created from Class2's __init__ function) I get an error message:
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
print instance2.attribute1
NameError: name 'instance2' is not defined
I don't know what the problem is, since name='instance3' and
exec name+'=Class1('attribute1') does work, though this is probably because I don't have much experience with Python. How would I be able to do something like this automatically when an instance is created?
I have to run, so hopefully, someone else can fix any mistakes in this post:
class Class1:
def __init__(self, attribute):
self.attribute1 = attribute
class Class2:
def __init__(self, instanceName):
setattr(self, instanceName, Class1(...)) # replace ... with whatever parameters you want

Why am I unable to perform a simple operation in the __init__ of my class?

Given below is a snippet from a class of which I am trying to create objects and getting error:
class FoF(object):
def __init__(self,path):
filepath=[]
filepath.append(self.FileOrFolder(path))
Upon executing which I get the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "PathOps.py", line 6, in __init__
def __init__(self,path):
NameError: global name 'filepath' is not defined
After which I tried:
filepath=[]
class FoF(object):
def __init__(self,path):
global filepath.append(self.FileOrFolder(path))
And again:
File "<stdin>", line 1, in <module>
File "PathOps.py", line 6, in __init__
global filepath.append(self.FileOrFolder(path))
NameError: global name 'filepath' is not defined
What is causing the error and how do I fix it?
Try using insted of global the special word self.
So something like this
class FoF(object):
def __init__(self,path):
self.filepath=[]
self.filepath.append(self.FileOrFolder(path))
The reason this error comes up is because what python thinks you're trying to do is one of two things:
Either you're trying to reference a global variable called filepath -- which is clear that's not what you're trying
What's not so clear is that you could also define a class attribute called filepath -- the only problem with that is that you can't define a class attribute with a function of that class. You can only do so within the class -- outside a class function
So in order to declare variables within a function you have to use the word self before it.
Edit** if you want it to be an attribute of the class -- as I'm assuming is what you meant you could do so like this:
class FoF(object):
filepath=[]
def __init__(self,path):
self.filepath.append(self.FileOrFolder(path))
I don't think you're giving us enough information. For example:
>>> class FoF(object):
... def __init__(self, path):
... junk = []
... junk.append(path)
...
>>> foo = FoF('bar/path')
produces no error.
What, exactly, are you trying to do?

Categories