Re: [Tutor] List comprehensions to search a list--amazing!
Patrick Thunstrom wrote: The generalized problem: L = [V0, V1, ..., Vn], where V0 = V1 = V2 = ... = Vn . Find index i, such that V[i] = Vt = V[i + 1], where Vt is the test value being searched for. I need to know the indices i and i + 1, which I need to interpolate based on where Vt falls. The solution (As a sublist, S) I worked out tonight after experimenting with comprehension syntax is: S = [i for i, V in enumerate(L) if L[i] = Vt = L[i + 1]] And, of course, the index i I need is: i = S[0] I tested this out with concrete examples in the interpreter, such as with a list, L: L = [item for item in range(1, 0, -1)] and trying different test values. It was blazingly fast, too! All I can say is: WOW!!! By the way, if you were to use a plain old loop the expected speedup over the listcomp would be 2. You can break out of the loop when you have found the gap, after iterating over one half of the list on average. So for-loops are twice as amazing ;) For the same basic speed up, a generator expression with a call to next() will produce similar results. Without the additional code to get the indexed item. index = (i for i, _ in enumerate(original_list) if original_list[i] = target = original_list[i + 1]).next() The only catch is it raises a StopIteration exception if no element fits the test. In new code you shouldn't call the next() method (renamed __next__() in Python 3) explicitly. Use the next() builtin instead which also allows you to provide a default: exhausted = iter(()) next(exhausted) Traceback (most recent call last): File stdin, line 1, in module StopIteration next(exhausted, default_value) 'default_value' That said, rather than polishing the implementation of the inferior algorithm pick the better one. Ceterum censeo bisect is the way to go here ;) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
Alan Gauld wrote: On 20/03/15 02:57, Doug Basberg wrote: Still, I would like to know if a 'hook' exists on exit from Python. I am running Linux on a Raspberry Pi with Python 2.7.4 I also run an Apache server on the Pi for monitor and control of power, HVAC, and security. Your previous mail got you three options. I'd use all of them! https://docs.python.org/3/library/atexit.html ... But that's only for normal program termination; sys.excepthook is for unexpected exits def close_relay(e=None,v=None,t=None): try: if not relay_closed() really_close_relay() except: really_close_relay() import sys, atexit atexit.register(close_relay) sys.excepthook = close_relay try: main program here finally: close_relay() That reeks of cargo cult. Are there actual scenarios for each of the three mechanisms where it is the only one that works? I would expect that try: main program here finally: close_relay() provides the same level of confidence, i. e. the relay will be closed when the program closes normally or the main code raises an exception, but not if the process is killed. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
On 20/03/15 04:50, Danny Yoo wrote: Some instructors out there do not realize that unit testing is considered a standard technique for introductory programming. Ask, and maybe that will change. Sadly, unit tests are not considered a standard technique for introductory programming. At least not in my part of the world. They should be, but they ain't. Or not at high school level(*). I've yet to meet a teacher who even discusses them in the sense of using unitest type frameworks - they do of course tell the kids to test their code but don't show them how! Many schools teach programming because they have to, but have no qualified staff in the subject, so a teacher, often a math or science teacher, gets sent off to do a course. He (usually he!) returns and teaches what was learned, guided by what is in the published syllabus. If the kids are really lucky they get somebody who taught themselves to code (probably in BASIC/VB) when they were a teenager... That's not how it should be of course, and the whole RaspberyPi movement is largely addressed at trying to remedy that situation. But I have a lot of sympathy for anyone being taught programming in the high schools around here just now (and for the poor, ill-equipped teachers too for that matter!) Disclaimer: Of course other places may have squadrons of properly trained and knowledgeable teachers. In which case, be very happy! (*) I'm not sure about the current state of play in universities. I know I was never taught anything about testing at university but things may well have moved on there. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
On Fri, Mar 20, 2015 at 08:35:34PM +, Alan Gauld wrote: Yeah, I know you can catch a signal and add your own handler, but I meant what is the default Python suspend behaviour? Does it execute any outstanding exception blocks? What about finally blocks? Or, if about to exit a context manager, the __exit__ method? Depends on the signal. I'm not an expert on how signals work in Linux, or other Unixes, but I expect that, in the absense of a specific signal handler to catch it, the sleep (pause?) signal will cause the interpreter to just stop and wait. I think that's signal 19 on Linux, and 18 to wake. Signal 9 doesn't give the interpreter to do anything. The OS just yanks the carpet out from under its feet and terminates the process with extreme prejudice. Signal 9 cannot be caught, no signal handlers will detect it, no try...finally blocks will run. The process just stops. Don't use kill -9 unless you need to. I always try three steps to kill a rogue process: First use kill processid with no other arguments. Give it 30 seconds or so to let the process tidy up after itself, and if it still hasn't quiet, try kill -HUP processid. Again, give it 30 seconds or so. Then, if and only if necessary, kill -9 processid. Or does it just stop and wait till its resumed? Kind of like an implicit yield statement? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
On 03/20/2015 06:20 PM, niyanax...@gmail.com wrote: Thank you Danny Yoo for replying. I figured out what to do for the isLegalMove but I ran into another problem. I now get a traceback error every chip is black. This is the traceback: Traceback (most recent call last): File C:\Python34\lib\tkinter\__init__.py, line 1487, in __call__ return self.func(*args) File u:\code\reversiguiapp.py, line 83, in _cbMouseClick TypeError: makeMove() takes 2 positional arguments but 3 were given Exception in Tkinter callback # Performs an actual move in the game. That is the current player places # one of his chips in the square at position (row, col). def makeMove( row, col ): Don't you need a 'self' parameter to this method, like all the others? if isALineOfAttack(row, col, 1, 1) is True : if self._currentPlayer == 1 : self._gameBoard[row, col] = BLACK else : self._gameBoard[row, col] = WHITE -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
On 03/20/2015 01:28 PM, niyanax...@gmail.com wrote: You have more than one copy of some lines of previous messages, and more than one version of code in the message. So I have to guess which one you intend to be current. Thank you Mark for replying. I fixed the note you provided on the isLegalMove. However the lineOfAttack function is a function my Professor did so students are not allowed to touch it. For the isOver function, are you able to guide me on that? I am very new to Comp Science and am still learning. I have attached the programs needed for testing to show that I am testing my code as well as the instructions provided for my project. Please help me out! # Returns a boolean indicating whether the game is over. def isOver(self) : isOver = 0 for i in range(8) : for j in range(8) : if self._gameBoard[i, j] != 0 : isOver + 1 The above line does NOT change isOver variable. Try again. By the way, it's not usually a good idea to use the function name as a local within the function, even though it'll work. if isOver == 64 : self._gameOver = True return True else: return False # Returns the def isLegalMove( self, row, col): if row 8 col: if self._gameBoard[row,col] != EMPTY: return True else: return False This function is still buggy. It does not return either True or False if the selected row is non-empty. # Returns the player number whose chip occupies the given square. def occupiedBy(self, row, col): How is the following function body any different from: return self._gameBoard[row, col] if self._gameBoard[row, col] == BLACK : return 1 if self._gameBoard[row, col] == WHITE : return 2 else: return 0 # Performs an actual move in the game. That is the current player places # one of his chips in the square at position (row, col). def makeMove( row, col ): if isALineOfAttack(row, col, 1, 1) is True : How are the four following lines any different from: self._gameBoard[row, col] = self._currentPlayer if self._currentPlayer == 1 : self._gameBoard[row, col] = BLACK else : self._gameBoard[row, col] = WHITE -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
Thank you Danny Yoo for replying. I figured out what to do for the isLegalMove but I ran into another problem. I now get a traceback error every chip is black. This is the traceback: Traceback (most recent call last): File C:\Python34\lib\tkinter\__init__.py, line 1487, in __call__ return self.func(*args) File u:\code\reversiguiapp.py, line 83, in _cbMouseClick TypeError: makeMove() takes 2 positional arguments but 3 were given Exception in Tkinter callback Here is my code again just in case: from ezarrays import Array2D # Values representing the color of the chips on the board. EMPTY = 0 BLACK = 1 WHITE = 2 class ReversiGameLogic : # Creates an instance of Reversi game logic with the board correctly # initialized and the current player set to black. def __init__(self) : # Use a 2-D array to represent the board. self._gameBoard = Array2D(8, 8) self._gameBoard.clear(EMPTY) # Set the initial configuration of the board. self._gameBoard[4,3] = BLACK self._gameBoard[3,4] = BLACK self._gameBoard[3,3] = WHITE self._gameBoard[4,4] = WHITE # Maintain the number of the current player. self._currentPlayer = BLACK # Keep track of the number of each players chips. self._numBlackChips = 2 self._numWhiteChips = 2 # A flag that is set when the game is over. That is, when there are # no empty squares on the board or neither player can make a move. self._gameOver = False # Returns a boolean indicating whether the game is over. def isOver(self) : isOver = 0 for i in range(8) : for j in range(8) : if self._gameBoard[i, j] != 0 : isOver = isOver + 1 if isOver == 64 : self._gameOver = True return True else: return False # Returns the player number of the current player. def whoseTurn(self) : if self._currentPlayer == 1: return 1 else: self._curentPlayer == 2 return 2 # Returns the number of chips on the board for the given player. def numChips(self, player) : chipCounter = 0 if player == 1 : for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == BLACK : chipCounter = chipCounter + 1 else : for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == WHITE : chipCounter = chipCounter + 1 return chipCounter # Returns the number of open squares on the board. def numOpenSquares(self) : numOpenSquares = 0 for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == EMPTY : numOpenSquares = numOpenSquares + 1 return numOpenSquares # Returns the player number of the winner or 0 if it's a draw. def getWinner( self ): player1 = 0 player2 = 0 if self._gameOver is True : for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == BLACK : player1 = player1 + 1 else : player2 = player2 + 1 if player1 player2 : return 1 if player2 player1 : return 2 else: return 0 # Returns the Return a Boolean indicating if the current player can place # their chip in the square at position (row, col). Both row and col must be # valid indices def isLegalMove( self, row, col ): if row 0 or row = 8 or col 0 or col = 8: return False if self._gameBoard[row,col] == EMPTY: return True else: return False # Returns the player number whose chip occupies the given square. def occupiedBy(self, row, col): if self._gameBoard[row, col] == BLACK : return 1 if self._gameBoard[row, col] == WHITE : return 2 else: return 0 # Performs an actual move in the game. That is the current player places # one of his chips in the square at position (row, col). def makeMove( row, col ): if isALineOfAttack(row, col, 1, 1) is True : if self._currentPlayer == 1 : self._gameBoard[row, col] = BLACK else : self._gameBoard[row, col] = WHITE # Helper method that returns a Boolean indicating if there is a line of # attack from cell (row, col) in the direction offset given by rowInc # and colInc. The direction offsets should be, 0, 1, or -1. def _isALineOfAttack(self, row, col, rowInc, colInc) : row += rowInc col += colInc # The next cell in the line must contain the opponents chip. if self.occupiedBy(row, col) == self._currentPlayer : return False # Traverse along the line and determine if it's a line of attack. while row = 0 and col = 0 and row 8 and col 8 : if self.occupiedBy(row, col) == self._currentPlayer : return True elif self.occupiedBy(row, col) == EMPTY : return False else :
Re: [Tutor] Fastest find in 2 2D lists with else statement
On Fri, Mar 20, 2015 at 08:22:03AM -0400, Kale Good wrote: Hello all, I'm new to python and a bit of a weekend-warrior programmer (guitar teacher by trade), so there are plenty of computer sciencey concepts that I haven't grasped yet, and I think I'm bumping up against those now. Read from separate csv files, I have something like a=[['bass',9],['eagle',36],['human',68]] b=[['bass','fish'],['eagle','bird'],['dog',land']] c=[[1,'fish','water'],[2, 'mammal','land'],[3,'bird','air']] What do the numbers 9, 36, 68 in a list mean? If I'm reading b correctly, you say a bass is a fish, an eagle is a bird, and a dog is a land. What do the numbers 1, 2, 3 in c list mean? What I want is to return where each animal lives. What I've been able to glisten from the manuals and stack overflow is: Let's start by writing in English how you would do this. My guess is: For each animal: find out what kind of animal it is; then look up where that kind of animal lives. This tells you that the most natural sort of information you want is a list of animals: # [...] is used for lists animals = [bass, eagle, human, spider, salmon] plus a dict that associates each animal with its kind: # {...} is used for dicts kinds = {bass: fish, eagle: bird, human: mammal, spider: arachnid, salmon: fish, } plus a second dict that maps each kind to a location: locations = {fish: water, bird: air, mammal: land, insect: land, arachnid: land, mollusk: water, } Then your code becomes trivially easy! for animal in animals: kind = kinds[animal] print(animal, lives in or on, locations[kind]) The dict lookup kinds[animal] takes care of all the searching for you, no need to write a for loop at all. To handle the case where the animal or kind is unknown: for animal in animals: kind = kinds.get(animal, None) if kind is None: # Ask the user what sort of kind of animal it is. # In Python 2, you MUST use raw_input instead of input! kind = input(What kind of animal is '%s'? % animal) kind = kind.strip().lower() kinds[animal] = kind location = locations.get(kind, None) if location is None: # Ask the user where this kind of animal lives. # In Python 2, you MUST use raw_input instead of input! location = input(Where do '%s' animals live? % kind) location = location.strip().lower() locations[kind] = location print(animal, lives in or on, location) Note that direct lookups into a dict are written with square brackets: kinds[animal] but optional lookups with a default value use round brackets (parentheses): kinds.get(animal, None) # None is the default. Also, there's nothing you can write in Python which will be faster than looking it up in a dict. If you have concerns about looping over lists repeatedly, you are right to worry about speed. But if you can get the same data into a dict or two, dict lookups are *blazingly* fast. Are you able to move your data into the list and dictionary formats shown above? The secret to programming successfully is that getting the data into the right format is half the battle. Once you have the data in the right format, everything else becomes so much simpler. For example, I might take your a list and convert it like this: a=[['bass',9],['eagle',36],['human',68]] animals = [sublist[0] for sublist in a] That extracts out the strings bass, eagle etc. and puts them into a list called animals. Converting your b list to a dict should be even easier: b=[['bass', 'fish'],['eagle', 'bird'],['dog', 'mammal']] kinds = dict(b) Can you work out how to get the locations you need, or do you need more help? Feel free to ask any questions you have! -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
Hi, This is mostly a distant footnote to Doug Basberg's original question, which I believe is largely answered at this point. Albert-Jan Roskum, Alan Gauld and Steven D'Aprano were asking about signals and how they are handled (in Un*xen). I am trying to address that. Yeah, I know you can catch a signal and add your own handler, but I meant what is the default Python suspend behaviour? Does it execute any outstanding exception blocks? What about finally blocks? Or, if about to exit a context manager, the __exit__ method? Suspension of the process has nothing to do with Python. This happens in the Un*x scheduler--long before Python is involved. Depends on the signal. Correct. It all depends on the signal. Short version: (Apologies, Jack Nicholson, in demonic form or otherwise): * You can't 'handle': STOP, CONT, KILL, SEGV, BUS. * You can handle: HUP, INT, QUIT, USR1, USR2, PIPE, ALRM, TERM and others. Short advice (though I do not have experience dealing with signals in a realtime environment). I suggest the following guidelines: 1. Do not catch a signal you cannot handle (or do not intend to handle). 2. Do everything you can at startup to make sure that the environment in which you are operating is as you expect. 3. Catch all the signals you want to catch and, in response to receiving such a signal, do what you need in order to shut down cleanly. This coexists peacefully with the handy atexit handlers suggested earlier. (I am normally not at all a fan of an unspecific try--finally, but I get what Peter Otten is suggesting and might make the same choice, were I faced with Doug Basberg's situation.) I'm not an expert on how signals work in Linux, or other Unixes, but I expect that, in the absense of a specific signal handler to catch it, the sleep (pause?) signal will cause the interpreter to just stop and wait. I think that's signal 19 on Linux, and 18 to wake. Longer version: I have experience with handling Linux signals and Python. There may be subtle differences on other Un*xen. If you wish to know more, I would suggest reading the chapter on Signals in _Advanced Programming in the Unix Environment_ (Chapter 10, in my second edition by Stevens Rago). You cannot catch nor handle: * SIGSTOP (19), because that tells Un*x, Please remove this process from the scheduler, i.e. freeze it! * SIGCONT (18), because that tells Unix, Please restore this process to normal scheduling, i.e. unfreeze it. * SIGKILL (9), because that tells Unix, Terminate this thing, with prejudice! Do not tell it what happened. This means, your Un*X will never actually deliver SIGSTOP, SIGCONT or SIGKILL to Python and your program. I believe that you cannot do anything with the following signals: * SIGSEGV (11), because this means that there has been a memory fault. Python is a sufficiently high-level language, that, if this happens, this should not be your code doing it. (Unless you are writing C extensions for Python, and then, of course, you know what you are doing) * SIGBUS (7), because this is extraordinarily rare (today), but would be a case of trying to access memory that does not exist. In practice, I have seen SIGSEGV often over the last 20 years (perhaps I have worked with flaky software, or perhaps that is just something that happens in this line of work). I have seen SIGBUS very rarely (usually a precursor to a machine eating itself for lunch). The signals STOP and CONT are so rarely exhibited that they are perceived as exotic specimens when demonstrated. The KILL signal is the big hammer that everybody learns in their first month using any Un*x (which is unfortunate because of the power it commands). Signal 9 doesn't give the interpreter to do anything. The OS just yanks the carpet out from under its feet and terminates the process with extreme prejudice. Signal 9 cannot be caught, no signal handlers will detect it, no try...finally blocks will run. The process just stops. Correct. When the (Linux | Un*x) kernel has a signal 9 for a process, that process does not get any chance to clean up. It simply disappears. It is never given an opportunity to run again--i.e. it will never be scheduled again. Don't use kill -9 unless you need to. I always try three steps to kill a rogue process: First use kill processid with no other arguments. Give it 30 seconds or so to let the process tidy up after itself, and if it still hasn't quiet, try kill -HUP processid. Again, give it 30 seconds or so. Then, if and only if necessary, kill -9 processid. Agreed. In my experience, most mature sysadmins do this, too. Or does it just stop and wait till its resumed? Kind of like an implicit yield statement? Sending a SIGSTOP to a process is equivalent to freezing it in memory/process space. I sometimes think of this as suspend (because of ctrl-Z in bash,
Re: [Tutor] Reversi Game Logic
On 03/19/2015 08:50 PM, niyanax...@gmail.com wrote: I am having trouble with a function in my reversi logic code. The function is the isLegalMove I am asked to Return a Boolean indicating if the current player can place their chip in the square at position (row, col). Both row and col must be valid indices. So I came up with my code below, however a move I make in the game says Error: not a legal move. Please help! I see lots of things wrong with the code, just by visual inspection. That should tell us that unit tests are necessary. If nothing else, unit tests help you refine just what each method is supposed to do, and under what conditions. I don't recall the rules for Othello, as it's been about 25 years since I've played it, and even then I didn't play much. But there are lots of things about the code that the comments don't describe. For example, it would seem from some of your code that the first player is always BLACK, and the second player is always WHITE. But in other places, you keep them distinct. I see Mark gave you a number of markers into your code for problems that already exist. So I'm going to concentrate only on the method you mention. # Returns the Finish the comment def isLegalMove( self, row, col): if row 8 and col 8: if self._gameBoard[row,col] != EMPTY: return True else: return False There are 3 exit points from the above function, and only two of them have return statements. Your unit test could detect that by assuring that the return value is always either True or False. The above function sometimes returns None. Have you been taught yet what happens when a function falls off the end without a return statement? -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
On Fri, Mar 20, 2015 10:37 AM CET Peter Otten wrote: Alan Gauld wrote: On 20/03/15 02:57, Doug Basberg wrote: Still, I would like to know if a 'hook' exists on exit from Python. I am running Linux on a Raspberry Pi with Python 2.7.4 I also run an Apache server on the Pi for monitor and control of power, HVAC, and security. Your previous mail got you three options. I'd use all of them! https://docs.python.org/3/library/atexit.html ... But that's only for normal program termination; sys.excepthook is for unexpected exits def close_relay(e=None,v=None,t=None): try: if not relay_closed() really_close_relay() except: really_close_relay() import sys, atexit atexit.register(close_relay) sys.excepthook = close_relay try: main program here finally: close_relay() That reeks of cargo cult. Are there actual scenarios for each of the three mechanisms where it is the only one that works? I would expect that try: main program here finally: close_relay() Is this (also) called a diaper pattern? Or is that name reserved for the antipattern with try-bare except, where the 'except' catches all the sh*t (pardon my language)? provides the same level of confidence, i. e. the relay will be closed when the program closes normally or the main code raises an exception, but not if the process is killed. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
Albert-Jan Roskam wrote: I would expect that try: main program here finally: close_relay() Is this (also) called a diaper pattern? Cool name, but most parents want the baby's faeces to go into the diapers whereas try ... bare except is notorious for swallowing useful information that should be propagated to the user or developer. Or is that name reserved for the antipattern with try-bare except, where the 'except' catches all the sh*t (pardon my language)? For try ... finally it's its raison d'être to execute some code no matter what. E. g. before the advent of with ... with open(...) as f: ... # use file # file is closed now even if something went wrong while using it and no # matter how garbage collection works for the Python implementation running # the code. # The exception (if any) is not swallowed it was good style to write f = open(...) try: ... # use file finally: f.close() # file is closed... ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
On 20Mar2015 19:20, Martin A. Brown mar...@linux-ip.net wrote: [...] Short version: (Apologies, Jack Nicholson, in demonic form or otherwise): * You can't 'handle': STOP, CONT, KILL, SEGV, BUS. You can handle SEGV and BUS. Though probably not meaningfully in Python, haven't tried; if they fire in Python something internal is already badly wrong. IIRC, in the distant past the Bourne shell used SIGSEGV as a trigger to allocate more memory:-) Really, the only 3 a UNIX process can't intercept are the first three: STOP, CONT, KILL. Since everything else Martin says seems to be in the context of in Python, no other quibbles. Cheers, Cameron Simpson c...@zip.com.au ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Fastest find in 2 2D lists with else statement
On 20/03/2015 12:22, Kale Good wrote: Hello all, I'm new to python and a bit of a weekend-warrior programmer (guitar teacher by trade), so there are plenty of computer sciencey concepts that I haven't grasped yet, and I think I'm bumping up against those now. Welcome to the club :) Read from separate csv files, I have something like a=[['bass',9],['eagle',36],['human',68]] b=[['bass','fish'],['eagle','bird'],['dog',land']] c=[[1,'fish','water'],[2, 'mammal','land'],[3,'bird','air']] What I want is to return where each animal lives. What I've been able to glisten from the manuals and stack overflow is: for i in range(len(a)): for x in range(len(b)): if a in b[x][1]: clss = (b[x][0]) occurrence w/ else statement for y in range(len(c)): if clss in c[y][1]: place = (c[y][2]) a[i].append(place) Classic newbie stuff that immediately flags up a code smell. You do not need to loop around Python containers using indexes. This is typically written something like. for animal in animals: doSomething(animal) However see my comment below, you probably don't need so many loops if you hold your data in dicts. a)I'd like to have an else statement; if a match isn't found in b, prompt the user for one of the values in c[:][0]. (no need to print the list c; the user will have that available elsewhere) b)Is there a faster way to do this? List a has ~300 elements, while list b has ~45000, so I'm curious if I can make it faster. Take a look at the DictReader here https://docs.python.org/3/library/csv.html as when it comes to looking things up dicts are far faster than lists. Try coding it up and come back to us if you get any problems. We don't bite although I have been known to bark :) -I only need to find the first match, so it seems a next statement would do the trick. However, I can't figure out how to use next for finding in two 2d arrays. -From my understanding, for this use, b needs to be a list. However, each line is unique, so it could be a set if necessary. Thanks in advance. Best, Kale -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
On 20/03/15 09:37, Peter Otten wrote: def close_relay(e=None,v=None,t=None): try: if not relay_closed() really_close_relay() except: really_close_relay() The purpose of the if clause is to ensure that if the function is called many times you only close the relay once (I surmised that more than once could be harmful?) import sys, atexit atexit.register(close_relay) sys.excepthook = close_relay atexit should be overkill, but it might be needed if for some reason the interpreter dies while performing the usual cleanup. excepthook replaces the usual exception mechanism with a clean up. This is needed for cases where an exception occurs before getting to the finally. We want to close the relay ASAP, not waiting till the interpreter decides to call the finally. try: main program here finally: close_relay() This is the happy path where everything shuts down as expected. That reeks of cargo cult. Are there actual scenarios for each of the three mechanisms where it is the only one that works? In real-time you never trust anything. Always cover your back. I would expect that try: main program here finally: close_relay() provides the same level of confidence, Only if the interpreter is behaving as normal. The hooks are to try (we hope) to catch cases where the interpreter has broken its normal flow. So the scenarios are: 1) an unexpected exception occurs - close the relay ASAP. - Use excepthook 2) The interpreter gets sent a kill or similar unexpected termination - use atexit because finally may not get called. (I'm not sure, so belt n' braces here) (BTW Does anyone know what the interpreter does when suspending - Ctrl-Z in Unix land?) 3) Normal program exit. Use the finally clause. But its only ever going to be a best endeavour, that's why Python is not suitable for true real-time/critical apps... But I'd never trust any environment to its usual behaviour if there is a possibility of something being broken. In this case the relay and its battery pack. the program closes normally or the main code raises an exception, but not if the process is killed. What's not clear in the Python documentation is how Python responds to a kill(or suspend). I'd hope the atexit got called even in a kill. I would not expect the finally to be executed. Of course, if its a seg fault you are probably stuffed either way... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
So let's say that in the unit tests. Add assertions that we want those four starred points to be legal moves. # import unittest class ReversiTests(unittest.TestCase): def testIslegalMoveOnExistingSpots(self): logic = ReversiGameLogic() # Placing on existing spots should not be legal. self.assertFalse(logic.isLegalMove(4, 3)) self.assertFalse(logic.isLegalMove(3, 4)) self.assertFalse(logic.isLegalMove(3, 3)) self.assertFalse(logic.isLegalMove(4, 4)) def testIsLegalMoveGood(self): logic = ReversiGameLogic() # But here are spots that should be legal. self.assertTrue(logic.isLegalMove(2, 3)) ... ## fill me in with the other three legal moves! if __name__ == '__main__': unittest.main() ## Sorry: I sent this draft a bit too early! There really should be at least one more test that we need to have; we need to check for moves that are not legal, but for fundamental Reversi-based reasons. For example, we *know* that playing on (1, 1) can't be legal when the game is starting: it's an empty spot on the board, but it's not adjacent to a line of white pieces. This is the sort of thing that would be an appropriate to write as a test: ### import unittest class ReversiTests(unittest.TestCase): def testIslegalMoveOnExistingSpots(self): logic = ReversiGameLogic() # Placing on existing spots should not be legal. self.assertFalse(logic.isLegalMove(4, 3)) self.assertFalse(logic.isLegalMove(3, 4)) self.assertFalse(logic.isLegalMove(3, 3)) self.assertFalse(logic.isLegalMove(4, 4)) def testIsLegalMoveGood(self): logic = ReversiGameLogic() # But here are spots that should be legal. self.assertTrue(logic.isLegalMove(2, 3)) ## ... fill me in with the other three legal moves! def testIsLegalMoveNotAdjacentAttackLine(self): logic = ReversiGameLogic() # But here is a spot that should be illegal. self.assertTrue(logic.isLegalMove(1, 1)) if __name__ == '__main__': unittest.main() You'll should see that one of the tests is succeeding, which is great! That's what you want to see: partial success. It means that you're going in the right direction, and that you just need to amend what you've got so far. It should also point out two concrete ways in which your program isn't quite working yet. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
Hi Ni'Yana, Here's a little transcript of what I'd do if I were to take a testing approach to the problem. --- Let's say that we start with a fresh board. Imagine that we've just created a fresh ReversiGameLogic. What does the board look like? Let's look at the state in the initializer. # def __init__(self) : # Use a 2-D array to represent the board. self._gameBoard = Array2D(8, 8) self._gameBoard.clear(EMPTY) self._gameBoard[4,3] = BLACK self._gameBoard[3,4] = BLACK self._gameBoard[3,3] = WHITE self._gameBoard[4,4] = WHITE self._currentPlayer = BLACK ... # Let's visualize this. The board looks like this: . . . . . . . . . . . . . . . . . . . . . . . . . . . W B . . . . . . B W . . . . . . . . . . . . . . . . . . . . . . . . . . . and we'll keep in mind that the current player is black. You mention the following: I am having trouble with a function in my reversi logic code. The function is the isLegalMove I am asked to Return a Boolean indicating if the current player can place their chip in the square at position (row, col). Both row and col must be valid indices. What moves are illegal when the board is just starting off? Well, if I try placing on the same points as what's already on the board, that's definitely wrong. Let me try writing this as a unit test. ## import unittest class ReversiTests(unittest.TestCase): def testIslegalMoveOnExistingSpots(self): logic = ReversiGameLogic() self.assertFalse(logic.isLegalMove(4, 3)) self.assertFalse(logic.isLegalMove(3, 4)) self.assertFalse(logic.isLegalMove(3, 3)) self.assertFalse(logic.isLegalMove(4, 4)) if __name__ == '__main__': unittest.main() ## I'd then run these tests, and they'd all pass, so I'd like that your code is doing *something* good. But then, I'd notice that the tests don't really say too much yet: they've only said that it's illegal to play where there's already a piece. What at the places where black can play when the board looks like this? . . . . . . . . . . . . . . . . . . . . . . . . . . . W B . . . . . . B W . . . . . . . . . . . . . . . . . . . . . . . . . . . According to: http://en.wikipedia.org/wiki/Reversi the legal places where black can play next are here, marked with *'s. . . . . . . . . . . . . . . . . . . . * . . . . . . * W B . . . . . . B W * . . . . . . * . . . . . . . . . . . . . . . . . . . So let's say that in the unit tests. Add assertions that we want those four starred points to be legal moves. # import unittest class ReversiTests(unittest.TestCase): def testIslegalMoveOnExistingSpots(self): logic = ReversiGameLogic() # Placing on existing spots should not be legal. self.assertFalse(logic.isLegalMove(4, 3)) self.assertFalse(logic.isLegalMove(3, 4)) self.assertFalse(logic.isLegalMove(3, 3)) self.assertFalse(logic.isLegalMove(4, 4)) def testIsLegalMoveGood(self): logic = ReversiGameLogic() # But here are spots that should be legal. self.assertTrue(logic.isLegalMove(2, 3)) ... ## fill me in with the other three legal moves! if __name__ == '__main__': unittest.main() ## If this is the first time you've seen a testing approach, notice that writing tests is a matter of asking yourself: if this is what the world looks like, what *should* happen if my code were working? That's an easier thing to do than to actually write the working code. But it's not just something that we ponder: it's something we can run! Once we have the other three legal moves in play, now we have something we can execute. This is something that will say yes or no to our implementation of isLegalMove(). This is the sort of thing we *need* in order to tell if the logic is working or not. It will also point out very clearly that your isLegalMove() is not working, since it's going to fail. But these are going to tell more than than things are broken: they're going to tell you that things are partially working, which is good! That is, if you have these tests in place, one of the tests will succeed, and the other will fail. And that failure is going to point out where you're missing something in your definition of isLegalMove(). ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Fastest find in 2 2D lists with else statement
Hello all, I'm new to python and a bit of a weekend-warrior programmer (guitar teacher by trade), so there are plenty of computer sciencey concepts that I haven't grasped yet, and I think I'm bumping up against those now. Read from separate csv files, I have something like a=[['bass',9],['eagle',36],['human',68]] b=[['bass','fish'],['eagle','bird'],['dog',land']] c=[[1,'fish','water'],[2, 'mammal','land'],[3,'bird','air']] What I want is to return where each animal lives. What I've been able to glisten from the manuals and stack overflow is: for i in range(len(a)): for x in range(len(b)): if a in b[x][1]: clss = (b[x][0]) occurrence w/ else statement for y in range(len(c)): if clss in c[y][1]: place = (c[y][2]) a[i].append(place) a)I'd like to have an else statement; if a match isn't found in b, prompt the user for one of the values in c[:][0]. (no need to print the list c; the user will have that available elsewhere) b)Is there a faster way to do this? List a has ~300 elements, while list b has ~45000, so I'm curious if I can make it faster. -I only need to find the first match, so it seems a next statement would do the trick. However, I can't figure out how to use next for finding in two 2d arrays. -From my understanding, for this use, b needs to be a list. However, each line is unique, so it could be a set if necessary. Thanks in advance. Best, Kale -- Kale Good: Guitar Instructor ♫ phillyguitarlessons.com http://phillyguitarlessons.com phone: (215)260-5383 * 4705 Baltimore Ave, Phila, PA 19143 :Mailing Lessons * 1867 Frankford Ave. Phila, PA 19125 :Lessons Google+ https://plus.google.com/b/105422331794047992190/ Facebook http://facebook.com/KaleGoodGuitarStudio Read my article The Seven Secrets to Six String Success http://www.guitarnoise.com/lesson/seven-secrets-to-six-string-success/ at GuitarNoise.com http://guitarnoise.com Leading the Journey from No-Skills-Guitarist to Talented Musician! ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Reversi Game Logic
I am very new to Comp Science and am still learning. I have attached the programs needed for testing to show that I am testing my code as well as the instructions provided for my project. Please help me out! Sent from Windows Mail From: Ni'Yana Morgan Sent: Friday, March 20, 2015 11:16 AM To: Mark Lawrence I am very new to Comp Science and am still learning. I have attached the programs needed for testing to show that I am testing my code as well as the instructions provided for my project. Please help me out! Sent from Windows Mail From: Mark Lawrence Sent: Friday, March 20, 2015 11:11 AM To: Ni'Yana Morgan please use reply all so everybody can benefit Kindest regards. Mark Lawrence. On Friday, 20 March 2015, 15:04, niyanax...@gmail.com niyanax...@gmail.com wrote: Thank you Mark for replying. I fixed the note you provided on the isLegalMove. However the lineOfAttack function is a function my Professor did so students are not allowed to touch it. For the isOver function, are you able to guide me on that? I am very new to Comp Science and am still learning. I have attached the programs needed for testing to show that I am testing my code as well as the instructions provided for my project. Please help me out! from ezarrays import Array2D # Values representing the color of the chips on the board. EMPTY = 0 BLACK = 1 WHITE = 2 class ReversiGameLogic : # Creates an instance of Reversi game logic with the board correctly # initialized and the current player set to black. def __init__(self) : # Use a 2-D array to represent the board. self._gameBoard = Array2D(8, 8) self._gameBoard.clear(EMPTY) # Set the initial configuration of the board. self._gameBoard[4,3] = BLACK self._gameBoard[3,4] = BLACK self._gameBoard[3,3] = WHITE self._gameBoard[4,4] = WHITE # Maintain the number of the current player. self._currentPlayer = BLACK # Keep track of the number of each players chips. self._numBlackChips = 2 self._numWhiteChips = 2 # A flag that is set when the game is over. That is, when there are # no empty squares on the board or neither player can make a move. self._gameOver = False # Returns a boolean indicating whether the game is over. def isOver(self) : isOver = 0 for i in range(8) : for j in range(8) : if self._gameBoard[i, j] != 0 : isOver + 1 if isOver == 64 : self._gameOver = True return True else: return False # Returns the player number of the current player. def whoseTurn(self) : if self._currentPlayer == 1: return 1 else: self._curentPlayer == 2 return 2 # Returns the number of chips on the board for the given player. def numChips(self, player) : chipCounter = 0 if player == 1 : for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == BLACK : chipCounter = chipCounter + 1 else : for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == WHITE : chipCounter = chipCounter + 1 return chipCounter # Returns the number of open squares on the board. def numOpenSquares(self) : numOpenSquares = 0 for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == EMPTY : numOpenSquares = numOpenSquares + 1 return numOpenSquares # Returns the player number of the winner or 0 if it's a draw. def getWinner( self ): player1 = 0 player2 = 0 if self._gameOver is True : for i in range(8) : for j in range(8) : if self._gameBoard[i, j] == BLACK : player1 = player1 + 1 else : player2 = player2 + 1 if player1 player2 : return 1 if player2 player1 : return 2 else: return 0 # Returns the def isLegalMove( self, row, col): if row 8 col: if self._gameBoard[row,col] != EMPTY: return True else: return False # Returns the player number whose chip occupies the given square. def occupiedBy(self, row, col): if self._gameBoard[row, col] == BLACK : return 1 if self._gameBoard[row, col] == WHITE : return 2 else: return 0 # Performs an actual move in the game. That is the current player places # one of his chips in the square at position (row, col). def makeMove( row, col ): if isALineOfAttack(row, col, 1, 1) is True : if self._currentPlayer == 1 : self._gameBoard[row, col] = BLACK else : self._gameBoard[row, col] = WHITE # Helper method that returns a Boolean indicating if there is a line of # attack from cell (row, col) in the direction offset
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
On 20/03/15 20:04, Albert-Jan Roskam wrote: (BTW Does anyone know what the interpreter does when suspending - Ctrl-Z in Unix land?) No experience with it, but I would first check the 'signal' module Yeah, I know you can catch a signal and add your own handler, but I meant what is the default Python suspend behaviour? Does it execute any outstanding exception blocks? What about finally blocks? Or, if about to exit a context manager, the __exit__ method? Or does it just stop and wait till its resumed? Kind of like an implicit yield statement? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] UPDATE: Is there a 'hook' to capture all exits from a python program?
- On Fri, Mar 20, 2015 8:05 PM CET Alan Gauld wrote: On 20/03/15 09:37, Peter Otten wrote: def close_relay(e=None,v=None,t=None): try: if not relay_closed() really_close_relay() except: really_close_relay() The purpose of the if clause is to ensure that if the function is called many times you only close the relay once (I surmised that more than once could be harmful?) import sys, atexit atexit.register(close_relay) sys.excepthook = close_relay atexit should be overkill, but it might be needed if for some reason the interpreter dies while performing the usual cleanup. excepthook replaces the usual exception mechanism with a clean up. This is needed for cases where an exception occurs before getting to the finally. We want to close the relay ASAP, not waiting till the interpreter decides to call the finally. try: main program here finally: close_relay() This is the happy path where everything shuts down as expected. That reeks of cargo cult. Are there actual scenarios for each of the three mechanisms where it is the only one that works? In real-time you never trust anything. Always cover your back. I would expect that try: main program here finally: close_relay() provides the same level of confidence, Only if the interpreter is behaving as normal. The hooks are to try (we hope) to catch cases where the interpreter has broken its normal flow. So the scenarios are: 1) an unexpected exception occurs - close the relay ASAP. - Use excepthook 2) The interpreter gets sent a kill or similar unexpected termination - use atexit because finally may not get called. (I'm not sure, so belt n' braces here) (BTW Does anyone know what the interpreter does when suspending - Ctrl-Z in Unix land?) No experience with it, but I would first check the 'signal' module import signal import sys def signal_term_handler(signal, frame): print 'got SIGTERM' sys.exit(0) signal.signal(signal.SIGTERM, signal_term_handler) https://nattster.wordpress.com/2013/06/05/catch-kill-signal-in-python/ 3) Normal program exit. Use the finally clause. But its only ever going to be a best endeavour, that's why Python is not suitable for true real-time/critical apps... But I'd never trust any environment to its usual behaviour if there is a possibility of something being broken. In this case the relay and its battery pack. the program closes normally or the main code raises an exception, but not if the process is killed. What's not clear in the Python documentation is how Python responds to a kill(or suspend). I'd hope the atexit got called even in a kill. I would not expect the finally to be executed. Of course, if its a seg fault you are probably stuffed either way... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor