Python Parameter Confusion - python

I'm a beginner, writing a Python Blackjack script, and got confused about whether or not a function (dealPlayer) needs a parameter. It works either way, with a parameter or without. I'm not sure if I've had a brain fart, or I've not learned something along the way. Here's the code:
import random
dealer = []
player = []
c = ""
deck = [2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,
9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,11]
def dealPlayer(deck):
cardOne = random.choice(deck)
cardTwo = random.choice(deck)
player.append(cardOne)
player.append(cardTwo)
deck.remove(cardOne)
deck.remove(cardTwo)
The question is, do I need (deck) as a parameter in the function? It works with or without (deck) as a parameter. I've gone back over different tutorials, and other's code, but I'm still confused. Thanks for any help.

The reason your code works with or without deck as a parameter is because there is a global variable named deck, so when you reference deck inside your function, the function will first look for the local variable (the parameter) and then if it doesn't find it, it will look for the global variable.
It's best to refactor your code to not use global variables at all -- define deck initially inside a function and then pass that as a result or argument to other functions as needed. If you don't want to do that, then at least make sure your argument does not shadow (have the same name as) the global variable, to avoid confusion further on. Or remove the argument entirely and use the global variable only, if that's appropriate for your program.

did i get you right that if your function is:
def dealPlayer():
the code still works? this should raise a undefined deck error. EDIT: this was wrong of course its global. And just works without it. but thats a bad practice.
def dealPlayer():
deck = []
this should raise a Index Error.
cardOne = random.choice()
This raises a TypeError.

Related

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.

Django: "referenced before assignment" but only for some variables

I'm writing a small app in Django and I'm keeping the state saved in a few variables I declare out of the methods in views.py. Here is the important part of this file:
from app.playerlist import fullList
auc_unsold = fullList[:]
auc_teams = []
auc_in_progress = []
auc_current_turn = -1
print(auc_in_progress)
def auc_action(request):
data = json.loads(request.GET["data"])
# ...
elif data[0] == "start":
random.shuffle(auc_teams)
print(auc_unsold)
print(auc_in_progress)
auc_in_progress = [None, 0, None]
print(auc_in_progress)
The auc_unsold and auc_teams variables work fine; the auc_in_progress variable is not seen by this method, though, giving the error in the title. If I take out the print statement and let this code assign a value to it, the exception will be thrown somewhere else in the code as soon as I use that variable again.
I have tried making another variable and this new one seems to suffer from this problem as well.
What is happening?
Edit: I found a solution: if I write global auc_in_progress just before the print statements, then everything works fine. If I try writing that as I declare the variable above it doesn't work, though, for some reason.
I am unsatisfied with this, because I don't know why this happens and because I dislike using global like that, but eh. Someone has an explanation?
You should absolutely not be doing this, either your original code or your proposed solution with global.
Anything at module level will be shared across requests, not only for the current user but for all users for that process. So everyone will see the same auction, etc.
The reason for your error is because you assign to that variable within your function, which automatically makes it a local variable: see this question for more details. But the solution recommended there, which is the same as your workaround - ie use global - is not appropriate here; you should store the data somewhere specifically associated with the user, eg the session.

Number of arguments in Tkinter classes

relative noob here! I'm running 2.7, if that helps.
I'm trying to call a function defined in my main application class in a different function (I think that's called inheritance?) But I keep having problems with the number of args I put into my function!
Here's the function (is it called a method? if not, what's a method) I'm trying to call:
def student_list_updater(self, list):
self.StudentListDisplay.delete(0, END)
for student in list:
self.StudentListDisplay.insert(END, student)
And here's the function I'm calling it in (it's inheriting student_list_updater, right?):
def OnRemoveClick(self, student_list_updater):
self.student_list_updater = student_list_updater
index = self.StudentListDisplay.curselection()
index = int(index[0])
del student_list_temp[index]
self.student_list_updater(student_list_temp)
Thank you for the help in advance!
It's a little difficult to understand your question without more of the code, but hopefully this answer points you in the right direction.
First, to clarify, methods are just functions that can be accessed through an instance of a class, so yes, these are methods, but they're also functions--don't get too hung up on it. Next, I don't think inheritance is necessary here--inheritance will be one class inheriting attributes from another, and I believe all of your methods are only in one class (correct me if I'm mistaken).
Now, as to your code: it's giving you an error that one of your methods takes a number of arguments, and you gave it a different number. Well, to me, it looks like you only need to pass one argument for this whole process: student_list_temp to student_list_updater(). Once again, I can't say for sure that this will solve your problems, based on the lack of code you posted, but this might work:
def student_list_updater(self, studentlist): #change list to studentlist,
self.StudentListDisplay.delete(0, END) #Python already has a list() method
for student in studentlist:
self.StudentListDisplay.insert(END, student)
def OnRemoveClick(self): #Remove student_list_updater from the args, it has no value
#self.student_list_updater = student_list_updater #this doesn't do anything
index = self.StudentListDisplay.curselection() #This part I can't really comment on
index = int(index[0]) #without knowing the contents of the
del student_list_temp[index] #Listbox and student_list_temp,
self.student_list_updater(student_list_temp) #but this should call student_list_updater()
#and update the Listbox if it's working
The last thing I want to point out is how you call OnRemoveClick() will probably change. If you're calling it from a Button, it would look like this:
self.btn = Button(self, text='GO', command=self.OnRemoveClick)
Note that you're not passing any arguments to it.
Hope that helps. You also might want to take a look at https://docs.python.org/2/tutorial/classes.html and https://docs.python.org/2/tutorial/modules.html to clear up any classes and functions questions you might have.

Turtle Function not being implemented

After finding a solution to my earlier question, I have been faced for a couple hours with a new problem with my Turtle functions. I am new to Python and turtle so I am not sure of the syntax that is needed for where to put commands (i.e. before or after defining the function) so that they will be implemented in the turtle module since I am trying to simulate a random turtle race, but it just keeps on coming up with the blank turtle screen with a black turtle in the center. What I am doing thats preventing the commands from working? So far thisis what I have but I would like to at least know I am getting the first part correct before I try to go any further with the rest:
import turtle
import random
t = turtle.Turtle('turtle')
v = turtle.Turtle('turtle')
s = turtle.Screen()
s.exitonclick()
def setup(turtle1, turtle2, s):
t = turtle1
v = turtle2
s.setworldcoordinates(0,0,50,50)
t.setposition(1,25)
t.up()
v.setposition(1,25)
v.up()
t.color('red')
v.color('red')
s = turtle.Screen()
s.exitonclick()
def newHeading(turtle, angleOfTipsiness):
t.setheading(random.randrange(-angleOfTipsiness, angleOfTipsiness))
v.setheading(random.randrange(-angleOfTipsiness, angleOfTipsiness))
I need the beginning picture to look like this : http://www.cs.ucsb.edu/~buoni/cs8/labs/lab02/start.JPG
Thank you!
You're not actually calling either the setup or the newHeading function. At the end of your code, you should have a top-level block looking like this:
# ...
def newHeading(turtle, angleOfTipsiness):
t.setheading(random.randrange(-angleOfTipsiness, angleOfTipsiness))
v.setheading(random.randrange(-angleOfTipsiness, angleOfTipsiness))
# after the end of the function definitions, add this:
if __name__ == '__main__':
# example calls, replace with ones that make sense for what
# you're trying to do:
setup(t, v, s)
newHeading(t, 10)
Several remarks on the code:
Your setup function should use the parameters turtle1 and turtle2, not assign them to new local variables t and v. (If the function parameters are too long to type over and over, just give them shorter names.) Likewise, newHeading doesn't use the turtle parameter at all.
t and v are confusing names for local variables because you already have global variables with the same names.
Global variables should be given long and descriptive names. Short names should be reserved for local variables, which are used more often, and in a more limited context.
In general, your function can either access the global variable and use the contained object as a global resource, or it can accept the object as a parameter and use it that way. Both are valid choices for some situations (the former is simpler, the latter more reusable), but you should not mix the two. If something is a global variable, don't also pass it as a parameter; if it is a parameter, use it instead of the global variable, even if the global is otherwise available. Mixing the two approaches for the same object will confuse the person maintaining the code later.

Categories

Resources