I have been trying to make a program that requires reading from a file and then making the string inside the file part of a string in the program. I have written an example of what I do:
gameinfo = [0,0]
def readsave(savefile):
"Reads a file and adds its statistics to variables"
filename = savefile
with open(filename) as file_object:
gameinfo = file_object.readlines()
print(gameinfo)
readsave('gamesave.txt')
print (gameinfo)
But whenever I run this code, all I seem to get is:
['thisworks\n', '7']
[0, 0]
The [0,0] string is what I am trying to change to ['thisworks\n, 7'], however it only changes inside the function. Is there any way which I can make this change global?
The problem here is scope, the gameinfo variable in the function is a local, not a global. You can declare it global, or pass gameinfo around as a parameter. Generally, I avoid global declarations as they can get confusing. I'd recommend passing gameinfo around:
def readsave(savefile, gameinfo=[0,0]): # Declare it as a default to the function.
"Reads a file and adds its statistics to variables"
with open(savefile) as file_object: # No need to rename this.
gameinfo = file_object.readlines()
return gameinfo # Return it so it escapes the scope of this function.
gameinfo = readsave('gamesave.txt') # Save it.
print(gameinfo) # Print it.
Variables are not shared in functions which means you define gameinfo = [0,0] but you are never actually getting that variable in the function. I you want to save in gameinfo you need to use return or global. global will make it possible to share variables inside the function and outside however this is considered bad practice so don't use it.
To use return simply put it in your function. Always make sure you have only one variable, string, integer returning once per call.
Here is your example rewritten to include the return statement I mentioned above:
gameinfo = [0,0]
def readsave(savefile):
"Reads a file and adds its statistics to variables"
filename = savefile
with open(filename) as file_object:
gameinfo = file_object.readlines()
print(gameinfo)
return gameinfo
gameinfo = readsave('gamesave.txt')
print (gameinfo)
You have also made a few other mistakes:
"Reads a file and adds its statistics to variables" is not a comment. Use """my text here""" (triple quotes) or #my text here to insert comments.
All these things you will learn as you read the Python tutorial. Here is one illustrating the use of return.
Related
Why is a variable interpreted differently when inserted into a function?
my_variable = ['list_item1','another_list_item']
var_name = [ i for i, a in locals().items() if a == my_variable][0]
print("The variable name is:", var_name)
def print_and_logging(input):
var_name = [ i for i, a in locals().items() if a == input][0]
print("The variable name is:", var_name)
print_and_logging(my_variable)
#Output
'''
The variable name is: my_variable
The variable name is: input
'''
Let's decompose this.
my_variable is the name by which you refer to an object, specifically an array containing two strings, ['list_item1','another_list_item']
This name exists in the outermost context of your code, the global namespace.
Now, when you are calling the function print_and_logging with the name my_variable as argument, what you are passing to it is not the name, but the object to which the name refers. The object is hence introduced in the context of the function, which forms a local namespace. The name by which the array object is introduced into (and therefore known to) this namespace is input. But that is still the same object.
If you experiment a bit more, you'll find that you can actually use the name my_variable inside your function, but that the name input is unknown outside of the function.
I think you'll find this post informative. Going forward, you might also want to make research on the concept of namespace and look how arguments are passed in python.
I have a piece of code that has used python exec() function. data is saved as an array in a file and when exec() is used, data type is specified as dictionary. I can't quit understand what's the output
style = dict()
# test.py includes one 10 x 10 array
with open('test.py')as output:
exec(output.read(), style)
Since you are passing empty dict() as globals argument for exec() output will not be defined when output.read() is executed. If you need to print the result of output.read() then you need to pass either globals() or locals() as second argument to exec. They return a dictionary containing objects available in global and local scope respectively. The new code may be:
style = dict()
with open('test.py') as output:
exec("print(output.read())", globals())
or
style = dict()
with open('test.py') as output:
exec("print(output.read())", locals())
Return value from exec statement is None so you need to use print to see the output of output.read()
I am new to Python and am at a lost as to what I'm doing wrong. I am trying to use the fqdn variable that is being returned to the caller which is main() but I'm getting NameError: name 'fqdn' is not defined
I'm betting this is some type of global variable statement issue or something like that, but I've been researching this and can't figure it out.
If a function from a module returns a value, and the caller is main(), shouldn't main() be able to use that returned value???
Here's the layout:
asset.py
def import_asset_list():
# Open the file that contains FQDNs
openfile = open(r"FQDN-test.txt")
if openfile.mode == 'r':
# Remove CR from end of each item
fqdn = openfile.read().splitlines()
# Add https to the beginning of every item in list
fqdn = ["https://" + item for item in fqdn]
openfile.close()
return fqdn
tscan.py
def main():
import asset
asset.import_asset_list()
# Iterate through list
for i in fqdn:
if SCHEDULED_SCAN == 1:
create_scheduled_scan(fqdn)
launch_scan(sid)
check_status_scan(uuid)
else:
create_scan(fqdn)
launch_scan(sid)
check_status_scan(uuid)
Short Explanation
Yes, main() should be able to use the returned value, but it's only the value that is returned, not the variable name. You have to define a variable of your own name, to receive the value, and use that instead.
Long Explanation
The name of a variable inside any function is simply a "label" valid only within the scope of this function. A function is an abstraction which means "Give me some input(s), and I will give you some output(s)". Within the function, you need to reference the inputs somehow and, potentially, assign some additional variables to perform whatever it is you would like to. These variable names have no meaning whatsoever outside the function, other than to, at most, convey some information as to the intended use of the function.
When a function returns a value, it does not return the "name" of the variable. Only the value (or the reference in memory) of the variable. You can define your own variable at the point where you call the function, give it your own name and assign to it the returned result of the function, so you simply have to write:
def main():
import asset
my_asset_list = asset.import_asset_list()
# Iterate through list
for i in my_asset_list:
if SCHEDULED_SCAN == 1:
create_scheduled_scan(my_asset_list)
launch_scan(sid)
check_status_scan(uuid)
else:
create_scan(my_asset_list)
launch_scan(sid)
check_status_scan(uuid)
I don't know where the uuid and the sid variables are defined.
To make sure you have understood this properly, remember:
You can have multiple functions in the same file, and use identically-named variables within all those functions, this will be no problem because a variable (with its name) only exists within each specific function scope.
Variable names do not "cross" the boundaries of the scope, only variable values/references and to do this, a special construct is used, i.e. the return [something] statement.
One of the parameter the I want to pass to a Class init is a variable with a string value. this string value is a name of a list. The init should use this string value to append the class object to that list. what I'm doing wrong?
I've tried using the locals() and globals() but it ended with "TypeError: unhashable type: 'list'". tried also vars() with no use as well.
refList = []
cmpList = []
class Part(object):
def __init__(self, origin, name, type, listName):
self.origin = origin
self.name = name
self.type = type
partListName = locals()[listName]
partListName.append(self)
#... some file parsing..
part1 = Part((str(origin), str(name) ,str(type), 'refList')
# ... some other file parsing ...
part2 = Part((str(origin), str(name) ,str(type), 'cmpList')
Welcome to SO Ram! I think you should rethink your code because this is not a good approach to do it always. It is better for example pass directly the list or something related.
However your issue with your code is that you should use the globals() function. I really recommend you see the next post in order to get more knowledge about how/when use this useful functionality of Python3.
Also, you must declarate your variables with global keywoard because you are going to reference this variables from your Part class.
global refList = []
global cmpList = []
Said all this, your critical code line should look like:
partListName = globals()[listName]
Consider following code:
##testing.py
namespace = "original"
def print_namespace():
print ("Namespace is", namespace)
def get_namespace_length(_str = namespace):
print(len(_str))
##Main
import testing
testing.namespace = "test"
testing.printnamespace()
testing.get_namespace_length()
print_namespace() return 'test' as exepcted, but the get_namespace_length() still return 8 which is the length of 'original'. How can I make get_namespace_length() taking the modified variable?
The use case of such implementation is some functions are used the same variable in the imported module, if I can modify/set variable, I can avoid explicitly to call out new variable in each function. Can someone advise?
Also, it doesn't have to be implemented in the way shown above, as long as it works. (global variable etc.)
Um... your default argument for get_namespace_length is database, undefined in your code snippet, also you switch from calling testing to test (I'm guessing that was one of many typos).
In short though, I believe its to do with how the bytecode is compiled in python. Arguments are 'preloaded', and therefore a change to a variable (such as namespace) does not get included in the compilation of get_namespace_length. If I remember correctly, upon import the entire code of the imported file is compiled and executed (try putting a print() statement at the end of testing.py to see)
So what you really want to do to obtain your length of 4 is change testing.py to:
namespace = "original"
def print_namespace():
print ("Namespace is", namespace)
def get_namespace_length():
_str = namespace
print(len(_str))
Or just print(len(namespace)).
Hope that helps!