Python Class variable not keeping value - python

I declared a class with a class variable.
Module name my_moudle_1.py
For example:
class my_class:
my_dict={}#The class variable
def __init__(self):
return
In a different module - my_moudle_2.py i wrote:
from my_moudle_1 import my_class
Inside this module there is a class. In the class method i wrote:
my_class.my_dict['123']=5
In third module - my_moudle_3.py i wrote again:
from my_moudle_1 import my_class
When i am checking the my_dict variable value in the instance of my_class, i get
that the value is {}.
How can i update in a different module the class variable and use it
inside an instance in a different file?
Thanks

That shouldn't be the case. I can't reproduce this problem:
mymod.py
class my_class:
my_dict = {}
def __init__(self):
return
my_class.my_dict['foo'] = 'bar'
mymod2.py
from mymod import my_class
my_class.my_dict['greeting'] = 'Hello'
testapp.py
from mymod import my_class
import mymod2 # will modify my_dict as a side effect
my_class.my_dict['barq'] = 'foo'
print(my_class.my_dict)
$ python3 testapp.py
{'foo': 'bar', 'greeting': 'Hello', 'barq': 'foo'}
$

Related

Is it possible to test a function that uses get_type_hints with a doctest?

I have a function that uses typing.get_type_hints. I want to add a documentation test to it. However, it looks like get_type_hints fails to resolve types that are defined in a doctest.
Here is a simplified example:
import typing
def f(clazz):
"""
>>> class MyClass:
... my_field: 'MyClass'
>>> f(MyClass)
"""
typing.get_type_hints(clazz)
When running it with python3 -m doctest test.py it throws NameError: name 'MyClass' is not defined.
In order to get it to work in doctest, you would need to provide the correct evaluation scope.
Try this:
import typing
def f(clazz, globalns=None, localns=None):
"""
>>> class MyClass:
... my_field: 'MyClass'
>>> f(MyClass, globals(), locals())
"""
typing.get_type_hints(clazz, globalns, localns)
In doctest, a special set of values are used in the "eval scope" that happens with get_typing_hints.
It is looking for "test.MyClass" which doesn't actually exist otherwise.
from __future__ import annotations
import typing
def f(clazz):
"""
>>> test = 1
>>> class MyClass:
... my_field:'MyClass'
>>> f(MyClass)
"""
typing.get_type_hints(clazz)
add from __future__ import annotations at the beginning of the file, it work for me on python3.7

Scope of Python Class Variable?

Are class variables essentially global variables?
Consider this example, in bar.py:
class Bar(object):
b = {}
then in foo.py:
def foo1():
import bar
bar.Bar.b["key"] = "foo1"
def foo2():
import bar
print bar.Bar.b.get("key", "foo2")
foo1()
foo2()
The "key" value is persistently "foo1."
For my purposes this seems like a global variable. But why isn't the class variable being reset or deleted between the calls to foo1 and foo2?
It's a class attribute. In your case, the dict is bound to the class Bar. Everytime you import bar, you get the same class bar.Bar (after all, it is in the bar's global namespace), and consequentially, you get the same dict bar.Bar.b.
If you want each Bar instance to have a different dict, you need to make an instance:
class Bar(object):
def __init__(self):
self.b = {}
And then:
def foo1():
import bar
bar.Bar().b["key"] = "foo1"
def foo2():
import bar
print bar.Bar().b.get("key", "foo2")
foo1()
foo2()
As far as why the module bar isn't being garbage collected, when you import something, python stores a reference to that module (see sys.modules). The next time you import that module, python picks out the proper item from sys.modules and gives you a reference to it. There are a few reasons for this.
Efficiency -- Why re-evaluate code you've already evaluated?
Sane behavior
Imagine a module with a special value:
# mod.py
CONSTANT = object()
now you want to use that in foo.py and bar.py.
# bar.py
import mod
def bar():
return mod.CONSTANT
# foo.py
import mod
import bar
if bar.bar() is mod.CONSTANT:
do_something()
If the import wasn't cached, then mod.CONSTANT could be different in foo and in bar which would be very surprising.

Getting an object by name

Is it possible to create an instance of a class by giving its name, e.g.:
instance = "TestXYZ"()
Assuming that TestXYZ is imported by a class that imports the code above and TestXYZ is defined as:
class TestXYZ(object):
...
Yes, it is possible. The mechanics depend on how you import the class:
>>> globals()["TestXYZ"]()
<__main__.TestXYZ object at 0x10f491090>
or
>>> getattr(sys.modules["test_module"], "TestXYZ")()
<test_module.TestXYZ object at 0x10cf22090>
You can get a reference to an object from current namespace using:
klass = globals()['TestXYZ']
Then you can create an instance of the class:
instance = klass()
I am not sure why do you want to do this, but instead of using globals() I'd suggest you to create a dictionary here:
class Foo:
pass
d = {'Foo':Foo}
ins = d['Foo']()
Or move the class to some other module:
import some_module
ins = getattr(some_module, 'Foo')()

__import__ and name is not found error in python

When a.py has this code:
class A():
def __init__(self):
print 'hi'
I use class A with this code:
import a
b = a.A()
I need to do the same thing with __import__, and I tried this page:Why does Python's __import__ require fromlist?
__import__("a", fromlist=[])
#import a
b = a.A()
However, I got name 'a' is not defined error. What might be wrong?
__import__ returns a module. You need to bind the result to a name:
a = __import__("a")
a.A()

import class defined in same module file?

I have a module file called mymodule.py, which contains the following code:
class foo:
def __init__(self):
self.foo = 1
class bar:
import foo
def __init__(self):
self.bar = foo().foo
The __init__.py file in the same directory has
from mymodule import foo
From a script in the same directory, I have the following code:
from mymodule import bar
When I try to run bar(), I get the error that No module named foo. How can I create an instance of foo in bar when they are defined within the same module file?
Classes are imported with module name first. However, you don't need to import classes in mymodule from within mymodule, just use it.
Meaning: remove the import foo line
You do not need to import an object defined in the same module:
class foo:
def __init__(self):
self.foo = 1
class bar:
def __init__(self):
self.bar = foo().foo
The import statement is intended for objects defined in other files only; you import the names defined in another python file into the current module.

Categories