Name Error when passing a parameter? - python

I am writing a program and keep on getting trouble with the error:
File "C:/Users//Documents///", line 47, in <module>
print(operations(sorted_list_desc))
NameError: name 'sorted_list_desc' is not defined
Even though you can not see the file I am working with, I have provided my code. I am supposed to loop the years and randomly choose an operator for each of the years. However, I keep on getting the error above. Any ideas why I keep on getting it?
import csv
#List to store different operators
list_operators = ["+","-","*","/"]
#Function to read file of list
def read_file():
#List to store data
sorted_list_desc = []
year = csv_file.readline()
population = csv_file.readline()
return sorted_list_desc
print(read_file())
def operations(sorted_list_desc):
for i in range(len(sorted_list_desc)):
operator = random.choice(list_operator)
return operator
print(operations(sorted_list_desc))
##

sorted_list_desc is generated by read_file(). Change your last line to:
print(operations(read_file()))
The line:
print(read_file())
does not magically created a global object withe name sorted_list_desc.
You need to hand it over explicitly to operations().
Alternatively, you could write:
sorted_list_desc = read_file()
print(operations(sorted_list_desc))

You have only assigned sorted_list_desc inside your function read_file(). Thus, your error is telling you that sorted_list_desc is not assigned to anything outside your function's scope. See Python scoping rules, and notice that you don't even need to pass sorted_list_desc as a parameter because it is assigned inside your function anyways.

Looks like sorted_list_desc is defined within the scope of your read_file() function and thus you can't reference it outside of that function. You can call print(operations(sorted_list_desc)) within 'read_file()', or you can define sorted_list_desc = [] at a global scope.

Related

Scopes and Customizing Open (learning Python p. 539)

I'm a bit confused about a code in the book "Learning Python", p. 539.
As far as I know assignments within a function are only in this local scope. So if I want to change a global one I first have to declare it global. But why does the following code change the builtin.open() to custom completely once called?
import builtins
def makeopen(id):
original = builtins.open
def custom(*pargs, **kargs):
print('Custom open call %r: ' % id, pargs, kargs)
return original(*pargs, **kargs)
builtins.open = custom
If I call makeopen('spam') and a F = open('text.txt') afterwards I get the custom call. So the builtin.open() has been changed in the whole script after the makeopen('spam'). Why?
And if I would make some more makeopen('xx') one builtin.open('text.txt') would print the custom call for every created makeopen. Why?
Comparing this code to
x = 99
def changing():
x = 88
changing()
print(x)
doesnt even help me. Isn't it the same but with an x instead of builtin.open()?
A variable is considered local if you assign to it anywhere in the function, unless you declare it global.
In your first piece of code, you never assign anything to builtins, so it's not considered local. You just change one of its attributes, open.
The rule is respected!
In your second piece of code, you assign something to x in x = 88, so it is considered local.
When you call makeopen, you replace the original, global open with custom. custom, when executed, prints its name and calls the original open.
If you call makeopen a second time, it will create a second, different custom function, and make the name builtins.open refer to it. When you call this function, it will print its name, then call original, which is what builtins.open referred to when it was created - and that is your first custom function, which will print its name and call the original open.
So, successive calls to makeopen create a chain of functions, and calling open will make each of them run and call its predecessor.

Module with text files

I am very new to python, and am writing a code with multiple modules.
Each of my modules manipulates the same list that I have named "myList", however, I am having trouble understanding how to get the list into each module.
For example, one module called reverseList.py needs to take the list and reverse it, but when it is run in my main function, I get an error that the list does not exist.
Import reverseList
def main():
with open('list3.txt', 'r') as f:
data = f.read()
data = data.split("\n")
myList = [row.split(",") for row in data]
reverseList.reverse()
NameError: name 'myList' is not defined
The reverseList.py module is as follows:
def reverse()
myList1 = myList[::-1]
print(myList1)
return
It is unclear where exactly the error comes out since you didn't include your entire main function - there is no place myList is used before/after its definition. But I can think of a couple of reasons for the error.
The error shows up when a variable is used before it is defined. So, you might have the variable myList before you define it in line 4 of your current code.
In python, indentation is the matter of correctness of your code. Meaning, line 2~4 should be indented if you didn't do so.
I might be able to come up with a better answer if you present the rest part of the code.
Your update reveals where the problem is happening; that is from your reverseList, not your main.
You are loading myList in reverseList, but it has never been defined. myList defined in main is not accessible from reverseList. To fix this problem, you should pass myList as an argument to the function reverse when it is called and use that in your reverse function.
main:
reverseList.reverse(myList)
reverseList:
def reverse(myList):
myList1 = myList[::-1]
print(myList1)
return
Note that the argument name of the function reverse can be different from the one in main. In other words, it doesn't matter if you do follow;
def reverse(myList2):
myList1 = myList2[::-1]
print(myList1)
return
This might be better:
def reverse(myList2):
print(myList2[::-1])

Passing a variable into a parameter defined by another function python

I am unsure of why the variable totalspeed variable is not being passed correctly to the function startgame as the startgame function is called after the gettotalspeed function.
Exerpt from call function:
gettotalspeed(party_ids)
NoOfEvents=0
startgame(party_ids,totalspeed,distance,NoOfEvents)
Functions
def gettotalspeed(party_ids):
#Get selected party members IDS
print(party_ids)
#Obtain Speeds
ids_string = ','.join(str(id) for id in party_ids)
mycursor.execute("SELECT startspeed FROM characters WHERE CharID IN ({0})".format(ids_string))
myspeeds=mycursor.fetchall()
totalspeed=0
for speedval in myspeeds:
totalspeed=totalspeed + speedval[0]
print("totalspeed is: ",totalspeed)
return totalspeed
def startgame(party_ids,totalspeed,distance,NoOfEvents):
#Check if game end
print(totalspeed)
while distance!=0:
#Travel...
distance=distance-totalspeed
NoOfEvents=NoOfEvents+1
#Generate Random Encounter
genevent(NoOfEvents)
return NoOfEvents
Error Produced:
NameError: name 'totalspeed' is not defined
Outputs (ignoring party_ids)
totalspeed is: 15
I suspect that your problem is self-evident from the main program:
gettotalspeed(party_ids)
NoOfEvents=0
startgame(party_ids,totalspeed,distance,NoOfEvents)
Of the variables you pass to your functions, only NoOfEvents is defined. party_ids, totalspeed, and distance have no definitions.
Work through a tutorial on Python scoping rules. Most of all, note that a function defines a scoping block. Variables inside the function are reclaimed when you leave the function; their names do not apply outside of that block. Your posted program has three independent totalspeed variables.
You forgot to make totalspeed a global variable like global totalspeed in your gettotalspeed() function. You might also be confused about what return does. If you wanted to do it the "proper" way, you could do totalspeed = gettotalspeed(party_ids). Hope this helps!

Python Pass function parameter as list identifier

I've created a function which can take a parameter which defines another call to manipulate a list. For example if I call sliprotor(Rotorid1, 1) directly, then the Rotorid1 list is manipulated as I want. Function below:
def sliprotor(rotorid,offset_qty):
for movers in range(26,0,-1):
rotorid[movers-1+offset_qty]=rotorid[movers-1]
for movers_refill in range(offset_qty):
rotorid[movers_refill]=rotorid[movers_refill+26]
However, if I try to call this 'indirectly' by building the list name and then executing it, 'rotorid' is not translated to the value, as it is when called directly.
The way I am doing this is
def set_curr_rotor(XX):
rotorid = "Rotorid"+str(XX)
return rotorid
rid1 = input("First rotor slip : ")
if(rid1):
sliprotor(set_curr_rotor(rid1),1)
So the 'indirect' call doesn't pass the value created by the set_curr_rotor function into the sliprotor function. The direct call does use the passed in value.
If I look in debug, you can see that it is directly calling rotorid[] as the list, not Rotorid1 or other Rotoridx and hence I get an index error.
....
File "", line 3, in sliprotor
rotorid[movers-1+offset_qty]=rotorid[movers-1]
IndexError: string index out of range
I could restructure the way I have the code, but I would prefer not to. Is there some method / scope issue I am missing? Is this just an intrinsic attribute of Python? I'm very new to Python so I'm just doing an exercise to model an Enigma machine.
Any help appreciated.
Ed
I'll assume that you have defined your rotors already, something like this:
Rotorid1 = list('abcdefghijklmnopqrstuvwxyz')
Rotorid2 = list('abcdefghijklmnopqrstuvwxyz')
And now you're reluctant to change this, because ... reasons.
That's fine. But you're still wrong. What you need to do is to create a larger data structure. You can do it like this:
Rotors = [ Rotorid1, Rotorid2, ... ]
Now you have a list-of-lists. The Rotors variable now contains all the various Rotorid variables. (Well, it references them. But that'll do.)
Instead of passing in the variable name as a handle to the rotor, you can simply pass in an index number:
def set_rotor(id):
global Current_rotor
Current_rotor = id
def slip_rotor(amount):
global Current_rotor
global Rotors
rotor = Rotors[Current_rotor]
for movers in range(26,0,-1):
rotor[movers-1+offset_qty]=rotor[movers-1]
# etc...
Also, be sure an look up slicings in Python - you can do a lot by manipulating sublists and substrings using slices.

SyntaxError when adding to a global set inside a function (Python)

I am trying to write a function that reads keywords from a file (in the format that each keyword is on a new line inside the text file)
I want the function to put the keywords into a global set() called "desiredItems".
desiredItems = set()
def populateDesired():
for line in open("desireditems.txt"):
addableLine = line.rstrip("\n")
global desiredItems.add(addableLine)
For some reason my development environment (Pycharm) tells me that desiredItems.add is invalid syntax.
(sorry If I have inserted code snippet incorrectly etc)
Thanks in advance
You don't need to use global at all, just remove it.
If you need to modify the binding of a global variable, the syntax is like this
def populateDesired():
global desiredItems
for line in open("desireditems.txt"):
addableLine = line.rstrip("\n")
desiredItems.add(addableLine)
Since you are not modifying the binding - merely calling a method, there is no need for global here at all
def populateDesired():
for line in open("desireditems.txt"):
addableLine = line.rstrip("\n")
desiredItems.add(addableLine)

Categories

Resources