Turtle Function not being implemented - python

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.

Related

Why do some of the methods in python's random module work without a class instance?

I have been learning python as my first programing language over the last few months, and up until now I felt like I had a decent understanding of functions, classes, and methods. However recently I was looking through python's random module and came across something that I cant quite figure out.
def randint(self, a, b):
#Return random integer in range [a, b], including both end points.
return self.randrange(a, b+1)
The above method is from the random module and is part of the Random() class, it is used to generate a random number between a and b. Because it's a method, it needs to be called on a class instance to satisfy the requirement for the 'self' argument.
import random
x = random.Random()
print(x.randint(1, 6))
In the above second block of code I am using this method to generate a random number between 1 and 6. This works as I expected it to because the variable x is being made into an instance of the Random() class, and then the randint() method is called on that instance with 1 and 6 passed in as the arguments a and b.
import random
print(random.randint(1, 6))
what I cant quite understand however is why this third block of code also works and achieves the same result. In this third example, there is no instance of the Random() class being created, and therefore nothing to satisfy the required "self" argument. I would have expected this to give me an error saying that 3 arguments are required (self, a, and b) but only 2 were provided (a and b). It is almost like this method is being treated like a regular function now and doesn't need to be called on a class instance anymore. Why is this? Is there something that I am missing here?
At the end of random.py a bunch of regular functions are defined to call methods on a generic instance:
_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
triangular = _inst.triangular
randint = _inst.randint
choice = _inst.choice
randrange = _inst.randrange
sample = _inst.sample
shuffle = _inst.shuffle
choices = _inst.choices
normalvariate = _inst.normalvariate
lognormvariate = _inst.lognormvariate
expovariate = _inst.expovariate
vonmisesvariate = _inst.vonmisesvariate
gammavariate = _inst.gammavariate
gauss = _inst.gauss
betavariate = _inst.betavariate
paretovariate = _inst.paretovariate
weibullvariate = _inst.weibullvariate
getstate = _inst.getstate
setstate = _inst.setstate
getrandbits = _inst.getrandbits
randbytes = _inst.randbytes
So random.randint(...) is equivalent to random._inst.randint(...). But you can't write that because names beginning with _ are not exported.
In this third example, there is no instance of the Random() class being created, and therefore nothing to satisfy the required "self" argument.
This is an incorrect assertion. Random is a somewhat special case in that the module itself provides these methods as quasi-static methods when the module is loaded (in addition to exposing them as instance methods) by creating a general-use instance straight off the bat and exposing that instance’s methods for use without an explicit instantiation in your top-level script.
You can find this (along with a helpful comment explaining this design choice) in the source code for Random.py:788-793:
# ----------------------------------------------------------------------
# Create one instance, seeded from current time, and export its methods
# as module-level functions. The functions share state across all uses
# (both in the user's code and in the Python libraries), but that's fine
# for most programs and is easier for the casual user than making them
# instantiate their own Random() instance.
Using these methods does limit you to using the current time as a seed for randomness, but that is generally sufficient for most use cases.

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!

Accessing variable of class-object instantiated in other file

I'm quite green on Python and have been looking around for an answer to my particular question. Though I'm not sure if it's a Python specific question, or if I'm simply getting my OOP / design patterns confused.
I've got three files: main.py, board.py and player.py. Board and player each only hold a class Player and Board, main simply starts the game.
However I'm struggling with validating player positions when they are added to the board. What I want is to instantiate the board and consecutively new player object(s) in main.py, but check the board size in player.py when a new player is added to the board, to ensure the player is not outside of bounds upon creation.
As it is now I'm getting a TypeError (getX() missing 1 required positional argument: 'self') when attempting to access the board's size inside of player.py.
Most likely because the board isn't instantiated in that scope. But if I instantiate it in the scope that will be counted as a new object, won't it? And if I pass the board to the player as a variable that would surely be counted as bad practice, wouldn't it?
So how do I go about accessing the instance variables of one class from another class?
I have no idea if this will help, but I made a post on how to save and load using the Pickle import. In the saving function, it refers back to the Player class I created. It might help you, it might not. Here is the link anyway.
Your question is asking about a concept called "dependency injection." You should take some time to read up on it. It details the ways of making one object available to another object that wants to interact with it. While that's too broad to write up here, here are some of the basics:
You could have all objects you care about be global, or contained in a global container. They can all see each other and interact with each other as necessary. This isn't very object-oriented, and is not the best practice. It's brittle (all the objects are tightly bound together, and it's hard to change or replace one), and it's not a good design for testing. But, it is a valid option, if not a good one.
You could have objects that care about each other be passed to each other. This would be the responsibility of something outside of all of the objects (in your case, basically your main function). You can pass the objects in every method that cares (e.g. board.verify_player_position(player1)). This works well, but you may find yourself passing the same parameter into almost every function. Or you could set the parameter either through a set call (e.g. board.set_player1(player1)), or in the constructor (e.g. board = Board(player1, player2)). Any of these are functionally pretty much the same, it's just a question of what seems to flow best for you. You still have the objects pretty tightly bound. That may be unavoidable. But at least testing is easier. You can make stub classes and pass them in to the appropriate places. (Remember that python works well with duck typing: "If it walks like a duck and quacks like a duck, then it's a duck." You can make testing code that has the same functions as your board and player class, and use that to test your functions.)
A frequent pattern is to have these objects be fairly dumb, and to have a "game_logic" or some other kind of controller. This would be given the instances of the board and the two players, and take care of maintaining all of the rules of the game. Then your main function would basically create the board and players, and simply pass them into your controller instance. If you went in this direction, I'm not sure how much code you would need your players or board to have, so you may not like this style.
There are other patterns that will do this, as well, but these are some of the more basic.
To answer your direct questions: yes, the error you're seeing is because you're trying to invoke the class function, and you need it to be on an object. And yes, instantiating in that case would be bad. But no, passing an instance of one class to another is not a bad thing. There's no use in having objects if they don't interact with something; most objects will need to interact with some other object at some point.
You mentioned that you have code available, but it's a good thing to think out your object interactions a little bit before getting too into the coding. So that's the question for you: do you want player1.check_valid_position(board), or board.check_player(player1), or rules.validate_move(player, some_kind_of_position_variable)`. They're all valid, and they all have the objects inter-relate; it's just a question of which makes the most sense to you to write.
It's hard to know your exact issue without seeing some code, but I hope this is useful!
class Player:
def __init__(self, x, y, player_id):
self.x = x
self.y = y
self.id = player_id
class Board:
def __init__(self, width, height):
self.width = width
self.height = height
self.players = {}
def add_player(self, player):
"""keep track of all the players"""
self._validate_player(player)
# add the player to a dict so we can access them quickly
self.players[player.id] = player
def _validate_player(self, player):
"""whatever validation you need to do here"""
if player.x < 0 or player.x >= self.width:
raise ValueError("The player didn't land on the board! Please check X")
if player.y < 0 or player.y >= self.height:
raise ValueError("The player didn't land on the board! Please check Y")
# whatever other checks you need to do
# player is in a valid location!
def main():
# we can make as few or as many players as we'd like!
p1 = Player(10, 20, 0)
p2 = Player(-1, 10, 1) # invalid player
board = Board(50, 50) # we only need to make one board
board.add_player(p1)
board.add_player(p2) # value error
running = True
while running: # simple game loop
player.take_turn() # maybe prompt user to input something
board.update_players() # update player positions
board.display()
running = board.keep_playing() # check for win state
# whatever code you want to run
if __name__ == "__main__":
main()
Here we create an instance of a Player by assigning an x and y position, and in this case also a player ID which we can use to get that player when we need them. If there's only going to be one player, we could just do something like board.player.
In my example, a ValueError is raised when an invalid Player is provided, you can of course do whatever you'd like in the event that a Player is invalid, also your game could have any number of other cases for a Player being invalid.
I've added some method calls for some methods that might make sense for a board game.
As a side note, in python, you generally don't need to write getters/setters, it's perfectly okay to access Class fields directly.
player.x = 10
if player.y == 11: etc.
and if you have need for validation of some sort that could belong in a getter/setter, you can use the #property decorator.

Python Parameter Confusion

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.

Scope, using functions in current module

I know this must be a trivial question, but I've tried many different ways, and searched quie a bit for a solution, but how do I create and reference subfunctions in the current module?
For example, I am writing a program to parse through a text file, and for each of the 300 different names in it, I want to assign to a category.
There are 300 of these, and I have a list of these structured to create a dict, so of the form lookup[key]=value (bonus question; any more efficient or sensible way to do this than a massive dict?).
I would like to keep all of this in the same module, but with the functions (dict initialisation, etc) at the
end of the file, so I dont have to scroll down 300 lines to see the code, i.e. as laid out as in the example below.
When I run it as below, I get the error 'initlookups is not defined'. When I structure is so that it is initialisation, then function definition, then function use, no problem.
I'm sure there must be an obvious way to initialise the functions and associated dict without keeping the code inline, but have tried quite a few so far without success. I can put it in an external module and import this, but would prefer not to for simplicity.
What should I be doing in terms of module structure? Is there any better way than using a dict to store this lookup table (It is 300 unique text keys mapping on to approx 10 categories?
Thanks,
Brendan
import ..... (initialisation code,etc )
initLookups() # **Should create the dict - How should this be referenced?**
print getlookup(KEY) # **How should this be referenced?**
def initLookups():
global lookup
lookup={}
lookup["A"]="AA"
lookup["B"]="BB"
(etc etc etc....)
def getlookup(value)
if name in lookup.keys():
getlookup=lookup[name]
else:
getlookup=""
return getlookup
A function needs to be defined before it can be called. If you want to have the code that needs to be executed at the top of the file, just define a main function and call it from the bottom:
import sys
def main(args):
pass
# All your other function definitions here
if __name__ == '__main__':
exit(main(sys.argv[1:]))
This way, whatever you reference in main will have been parsed and is hence known already. The reason for testing __name__ is that in this way the main method will only be run when the script is executed directly, not when it is imported by another file.
Side note: a dict with 300 keys is by no means massive, but you may want to either move the code that fills the dict to a separate module, or (perhaps more fancy) store the key/value pairs in a format like JSON and load it when the program starts.
Here's a more pythonic ways to do this. There aren't a lot of choices, BTW.
A function must be defined before it can be used. Period.
However, you don't have to strictly order all functions for the compiler's benefit. You merely have to put your execution of the functions last.
import # (initialisation code,etc )
def initLookups(): # Definitions must come before actual use
lookup={}
lookup["A"]="AA"
lookup["B"]="BB"
(etc etc etc....)
return lookup
# Any functions initLookups uses, can be define here.
# As long as they're findable in the same module.
if __name__ == "__main__": # Use comes last
lookup= initLookups()
print lookup.get("Key","")
Note that you don't need the getlookup function, it's a built-in feature of a dict, named get.
Also, "initialisation code" is suspicious. An import should not "do" anything. It should define functions and classes, but not actually provide any executable code. In the long run, executable code that is processed by an import can become a maintenance nightmare.
The most notable exception is a module-level Singleton object that gets created by default. Even then, be sure that the mystery object which makes a module work is clearly identified in the documentation.
If your lookup dict is unchanging, the simplest way is to just make it a module scope variable. ie:
lookup = {
'A' : 'AA',
'B' : 'BB',
...
}
If you may need to make changes, and later re-initialise it, you can do this in an initialisation function:
def initLookups():
global lookup
lookup = {
'A' : 'AA',
'B' : 'BB',
...
}
(Alternatively, lookup.update({'A':'AA', ...}) to change the dict in-place, affecting all callers with access to the old binding.)
However, if you've got these lookups in some standard format, it may be simpler simply to load it from a file and create the dictionary from that.
You can arrange your functions as you wish. The only rule about ordering is that the accessed variables must exist at the time the function is called - it's fine if the function has references to variables in the body that don't exist yet, so long as nothing actually tries to use that function. ie:
def foo():
print greeting, "World" # Note that greeting is not yet defined when foo() is created
greeting = "Hello"
foo() # Prints "Hello World"
But:
def foo():
print greeting, "World"
foo() # Gives an error - greeting not yet defined.
greeting = "Hello"
One further thing to note: your getlookup function is very inefficient. Using "if name in lookup.keys()" is actually getting a list of the keys from the dict, and then iterating over this list to find the item. This loses all the performance benefit the dict gives. Instead, "if name in lookup" would avoid this, or even better, use the fact that .get can be given a default to return if the key is not in the dictionary:
def getlookup(name)
return lookup.get(name, "")
I think that keeping the names in a flat text file, and loading them at runtime would be a good alternative. I try to stick to the lowest level of complexity possible with my data, starting with plain text and working up to a RDMS (I lifted this idea from The Pragmatic Programmer).
Dictionaries are very efficient in python. It's essentially what the whole language is built on. 300 items is well within the bounds of sane dict usage.
names.txt:
A = AAA
B = BBB
C = CCC
getname.py:
import sys
FILENAME = "names.txt"
def main(key):
pairs = (line.split("=") for line in open(FILENAME))
names = dict((x.strip(), y.strip()) for x,y in pairs)
return names.get(key, "Not found")
if __name__ == "__main__":
print main(sys.argv[-1])
If you really want to keep it all in one module for some reason, you could just stick a string at the top of the module. I think that a big swath of text is less distracting than a huge mess of dict initialization code (and easier to edit later):
import sys
LINES = """
A = AAA
B = BBB
C = CCC
D = DDD
E = EEE""".strip().splitlines()
PAIRS = (line.split("=") for line in LINES)
NAMES = dict((x.strip(), y.strip()) for x,y in PAIRS)
def main(key):
return NAMES.get(key, "Not found")
if __name__ == "__main__":
print main(sys.argv[-1])

Categories

Resources