I am looking for a code by using which I can make objects global.
What I am looking is - suppose there is one file xyz.py which has code
import some_module
class classname:
def __init__():
pass
def createobj():
some_module_obj = some_module()
and there are other two files 1.py and 2.py which has code
1.py
import xyz
obj = classname()
obj.sayhi()
2.py
import xyz
obj.sayhi()
I want to use the same object in 2.py created once in 1.py
Can anyone help me to know how can i achieve this.
Thanks,
Vipul
2.py
import xyz
print xyz.obj
or
from xyz import obj
print obj
You cannot create a name which is known and refers to the same object in all modules. Each module has its own global namespace.
But you can of course access the namespace of other modules by using qualified names.
EDIT:
Using module names like 1 (i. e. in files called 1.py) or similar is no good idea because a number cannot be used as an identifier. Qualified names like 1.obj are a syntax error. So I will use the files one.py and two.py instead, then I can access one.obj without this trouble.
If in file one.py you have sth like
obj = "foo"
then you can import this in file two.py:
import one
print one.obj # or use it any way you like
If you import it like this:
from one import obj
Then you will still have the same object:
print obj == one.obj # will print True (they are equal)
print obj is one.obj # will print True (they are the same)
but in a different variable named obj:
obj = "bar"
print obj, one.obj # will print "bar foo"
That the two variables are not the same only matters in case you assign sth to them.
So, if you want to be able to change the value (and have the change have effect in all using modules), you can either use the qualified name (one.obj) everywhere:
import one
one.obj = "bar"
or, instead of assigning a new value to the variable, you can change the existing value. This will also have effect in all using modules:
one.py:
obj = [ "foo" ]
two.py:
from one import obj
obj[0] = "bar"
This will also have effect in one.py even if our obj is a different variable than one.obj because both variables reference the same list.
If possible, I would propose to use the version using qualified names of course because the reference thing is hiding the mechanism and will probably surprise the next developer.
Related
Suppose file_A.py is written as so:
#file_A.py
my_object = create_new_object()
def update_object():
global my_object
my_object = update(my_object)
and then in file_B.py we do as so:
#file_B.py
from file_A import my_object, update_object
def process_object(object):
#do some operation ...
process_object(my_object) #first call to process_object()
update_object()
process_object(my_object) #second call to process_object()
My question is, when the second call to process_object() is made, will it use the original version of my_object ,which is imported at the top of file_B.py, be used, or will it use the updated version which replaces my_object when the update_object() function is called from file_B.py?
Variables are passed by reference. In file_A you will update the modules reference to my_object but the value imported in file_B will still have the old reference. For example:
Say I have file testA.py
a = 1
def foo():
global a
a = 2
And testB.py
from testA import a, foo
print(a)
foo()
print(a)
If I run testB.py you will get the output 1,1
This is because the global only updated the reference attached to the module testA.py. If you were to access the module however, then you would see it did update there. An example where you access the module instead
testC.py
import testA
print(testA.a)
testA.foo()
print(testA.a)
This will output 1, 2
Note that the same variable (even if global) can have different values in different python modules. Thus the best way to reference a variable from another module is by using module.variable
So your code might look like
import file_A
print(file_A.my_object)
file_A.process_object(file_A.my_object)
file_A.process_object(file_A.my_object)
print(file_A.my_object)
The key to referencing the right variable is to use the module name.
This can also be useful when you are working with multiple files and you need to keep some global variables.
This question may sound similar to the following, but I'm not sure how to apply their solutions to my use-case:
How to import a module given the full path?
Can you use a string to instantiate a class?
I have a class Foo defined and imported in my project. However, at runtime I may have a string containing a different definition of Foo (along with lots of other classes and import statements). I'd like to be able to replace the already loaded Foo with the one in my string, in a way that after the operation, anybody who instantiates f = Foo() would instantiate the definition from my string. At the same time, I'd like to ignore any other definitions/imports in my string. How to do this?
Assume the following project structure and use-case:
project/
__init__.py
mytypes/
__init__.py
foo.py # contains the definition 'class Foo'
another_package/
bar.py
main.py
Inside main.py and bar.py I have from mytypes.foo import Foo. After the replace operation detailed above I want both to use the new definition of Foo from the replacement string, but no other definition from my string.
The short answer is: don't do this. You will run into all kinds of strange errors that you will not expect
You can use exec to run some arbitrary code, if you pass a dictionary as the second argument the resulting "globals" from the executed string will be stored in the dictionary
namespace = {}
exec('class Foo:\n x = 10', namespace)
namespace['Foo'] # This will be a class named Foo
You could then assign this to the module
import your_module
your_module.Foo = namespace['Foo']
Now anywhere that your_module.Foo is accessed you will get the class from your string.
However, your module may have been imported at some time before you have patched it, it's very difficult to be able to say for certain when your module will be imported. Someone may have bound Foo using from your_module import Foo, if this has run before your patch then you will not change this Foo class. Even if you only ever access your_module.Foo, if an instance has been initialised before your patch then any subsequent instances will not even have the same type!
f = your_module.Foo()
# run your patch
isinstance(f, your_module.Foo) # False
In the case above f is an instance of a completely different type to the current your_module.Foo
This question already has answers here:
What does if __name__ == "__main__": do?
(45 answers)
Closed 8 months ago.
i cant seem to make this work.
I have 2 python files, lets say a.py and b.py
in a.py is this:
def foo():
global name
name = "foo"
import b
b.bar()
if __name__ == "__main__":
foo()
in b.py this:
import a
def bar():
name = a.name
print(name)
I have three different question in relation to this code:
Why do i get the error: AttributeError: 'module' object has no attribute 'name'
I know for certain that b.py cant access the variable defined in the function in b.py but how do i solve this?
does global in this case changes anything? if not, why?
i tried doing name = a.foo.name instead of name = a.name but this doesnt do the trick either and gives me: AttributeError: 'function' object has no attribute 'name',
is this even practicable in any case and what did i do wrong?
Thanks for taking the time and sorry if this seems obvious to some of you, i'am still getting into this.
Scripts aren't modules. Its something of a mind bender but when you run python3 a.py, a.py isn't a module (or more properly, its a module named __main__) and it will be reloaded when you import.
Suppose I have c.py
print('hello')
if __name__=="__main__":
import c
When I run it I get
hello
hello
To illustrate with your example, if I change b.py to
import __main__
def bar():
name = __main__.name
print(name)
It works. But only kindof because if somebody imports a you've still got two modules and two copies of the variable.
If you want shared data, they have to be in imported modules, not top level scripts. When I want shared data, I create a separate module that doesn't import anything (or only imports from the standard library) and it is either empty or has defaults for the variables I want to share.
1, 2) The specific purpose of if __name__ == "__main__": is to contain code that will not run when the file is imported. Since foo() is inside that block and nowhere else, the foo function does not run when import a happens; therefore the global name is not assigned to; therefore the a module does not have a name global; therefore b cannot refer to the nonexistent module global with a.name.
a.foo.name cannot fix the problem because, although a.foo exists (there is a foo function defined in the a module at the top level), it does not have a name attribute. The local variables in a function's code are not part of the function object; they exist only temporarily, while the code is running, and are not inherently part of any object. (Even if you call locals(), that creates a new dict, and assigns the local variables as values.)
It is possible to assign attributes to a function - for example, in a.py:
def foo():
pass
foo.name = "bar"
And such an attribute can be used from outside, including in another module:
# b.py
import a
print(a.foo.name)
But this is entirely orthogonal to what the function actually does, or to using it for any particular purpose.
Is it possible to dynamically name a function in a script as the name of the script? For example, if the script is called foo.py, is it possible to dynamically name a function in foo.py as foo? The reason I'm asking is that I import functions from several scripts and the naming convention is function_to_import = script - and to avoid any misspelling in the functions I'd like it to be dynamic. Thanks!
Yes, you can do something like
def main():
pass
globals()[__name__] = main
# if you no longer want the function to exist under its original name
del main
Messing with globals() is not generally recommended. I think it would make for clearer code to just bite the bullet and manually type out the name you need, but this is probably not the worst thing to do.
Note that this only changes the name that the function can be accessed with. It doesn't change the name of the underlying function object that you're accessing. If your code relies on that name, then you will have to do something more complicated.
There are multiple ways to assign a new name to a function, please note this would not change the name of the function, but the new name would also be pointing to that function.
Example 1 - While importing you can use as keyword to assign a new name, and then use it in the script using the new name
from foo import func as foo
foo()
Example 2 - You can assign the function to a new variable (a new name) and then use the new name to call it -
>>> def func(a):
... print("Hello")
...
>>> foo = func
>>> foo(1)
Hello
There may be more ways to do this.
You can use __file__ to get the filename and then assign the function to that file.
def my_function():
print "Hello, World!"
exec(__file__.split('.')[0] + " = my_function")
If you add this to your file, it will dynamically name the function my_function as the name of your file.
I was just curious if it was possible to create a module object inside python at runtime, without loading from any python file. The purpose of this would be to create a new empty namespace where other objects can then be stored subsequently. If this is not possible, is there another way to make and pass namespaces in python without saving to disk?
You can use a class with static methods.
class Namespace:
#staticmethod
def greet():
print "hello, world!"
In Python 3 the #staticmethod decorator is not needed.
You can use a simple class:
class Namespace:
pass
Now, to create a new namespace:
n = Namespace()
To store things in the namespace:
n.foo = 1
def square(x):
return x*x
n.squared = square
To refer to things in the namespace:
print n.foo
print n.squared(12)
To pass the namespace:
def func_requiring_a_namesapce(space):
print space.foo
func_requiring_a_namespace(n)
You could use a dictionary?
Modules Are Like Dictionaries
You know how a dictionary is created and used and that it is a way to map one thing to another. That means if you have a dictionary with a key 'apple' and you want to get it then you do this:
mystuff = {'apple': "I AM APPLES!"}
print mystuff['apple']
Imagine if I have a module that I decide to name mystuff.py and I put a function in it called apple. Here's the module mystuff.py:
# this goes in mystuff.py
def apple():
print "I AM APPLES!"
Once I have that, I can use that module with import and then access the apple function:
import mystuff
mystuff.apple()
I could also put a variable in it named tangerine like this:
def apple():
print "I AM APPLES!"
# this is just a variable
tangerine = "Living reflection of a dream"
Then again I can access that the same way:
import mystuff
mystuff.apple()
print mystuff.tangerine
Refer back to the dictionary, and you should start to see how this is similar to using a dictionary, but the syntax is different. Let's compare:
mystuff['apple'] # get apple from dict
mystuff.apple() # get apple from the module
mystuff.tangerine # same thing, it's just a variable
In the case of the dictionary, the key is a string and the syntax is [key]. In the case of the module, the key is an identifier, and the syntax is .key. Other than that they are nearly the same thing.
Editied from here