When I use the code:
def Jack():
global PHand
if 11 or 24 or 37 or 50 in PHand:
PHand.remove(11 or 24 or 37 or 50)
PHand.append("Jack")
I get an error saying list.remove(x) x is not in PHand, my question is, shouldn't the if check prevent this error?
You're basically checking to see whether 11 is true. It's non-zero, so your if always executes. What you want is:
if 11 in PHand or 24 in PHand or 37 in PHand or 50 in Phand:
Of course, your PHand.remove always tries to remove 11 for much the same reason. You can't tell remove to remove any of those (not sure where you got the idea that would even work, it's not in any documentation I've ever seen), so you should structure it so:
if 11 in PHand:
PHand.remove(11)
PHand.append("Jack")
if 24 in PHand:
PHand.remove(24)
PHand.append("Jack")
... and so on.
Of course you'd be better off refactoring that into a loop or even a function, rather than repeating all that code.
You need to iterate over each element:
for i in (11, 24, 37, 50): # assign i to 11, then 24, then 37, then 50
if i in PHand: # check each one in PHand
PHand.remove(i) # and remove that one
PHand.append("Jack") # your code
break # end the loop. remove this to check all
Otherwise, 11 or 24 or 37 or 50 in PHand outputs 11. Try it!
>>> 11 or 24 or 37 or 50 in PHand
11
Why? the way or works, it checks if the first side is truthy. If it is, it doesn't bother evaluating the rest, since the result couldn't change. If it weren't truthy, it would move on to the next argument, and so on.
And what of the in PHand? That actually gets evaluated first, to just the last number like this:
11 or 24 or 37 or (50 in PHand)
But again, 11 short-circuits all the ors.
Long story short:
or always returns a single value, not all values at once applied to functions repeatedly or however your syntax implies.
Just another way of solving it using filter:
def Jack():
T = [11,24,37,50]
found = filter(lambda x:x in T, PHand)
if found:
[PHand.remove(x) for x in found]
PHand.append('Jack')
PHand = range(10,55)
Jack()
Related
WHAT'S THE MISTAKE HERE??
Traceback (most recent call last)
<ipython-input-51-cb088c4c5c82> in <module>
17 display_board(the_board)
18 position = player_choice(the_board)
---> 19 place_marker(the_board,Player1_marker,position)
20 if win_check(the_board,Player1_marker):
21 display_board(the_board)
<ipython-input-41-ba563e2cb168> in place_marker(board, marker, position)
1 def place_marker(board, marker, position):
----> 2 board[position] = marker
TypeError: list indices must be integers or slices, not NoneType
The lines shown state exactly what is wrong, and where. You just need to know how to interpret it:
18 position = player_choice(the_board)
---> 19 place_marker(the_board,Player1_marker,position)
1 def place_marker(board, marker, position):
----> 2 board[position] = marker
TypeError: list indices must be integers or slices, not NoneType
What you can glean from all that is that:
the position variable used in line 2 of place_marker() is set to None since that is the actual error (variables set to None are of the type NoneType, and position is the list index being complained about);
that position variable is initialised from a variable of the same name, as part of the call to place_marker() on line 19, so it too must also be set to None;
that variable (the one passed in) came from the function player_choice().
In other words, your line:
position = player_choice(the_board)
has returned None for some reason.
Unfortunately, since you haven't shown us that code for that function, we can't really dive any deeper into the analysis, but you may want to look for paths in that function that return without a value. This is a typical cause of functions returning None, such as with:
def fn(x):
if x == 1:
return 7 # This path returns 7 when 1 is passed in.
# This path returns None (implicitly) for any other value.
print(fn(1)) # Explicitly gets 7.
print(fn(2)) # Implicitly gets None.
The result of running that code is, as per the comments:
7
None
At work, I stumbled upon an except clause with an or operator:
try:
# Do something.
except IndexError or KeyError:
# ErrorHandling
I know the exception classes should be passed as a tuple, but it bugged me that it wouldn't even cause a SyntaxError.
So first I wanted to investigate whether it actually works. And it doesn't.
>>> def with_or_raise(exc):
... try:
... raise exc()
... except IndexError or KeyError:
... print('Got ya!')
...
>>> with_or_raise(IndexError)
Got ya!
>>> with_or_raise(KeyError)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in with_or_raise
KeyError
So it did not catch the second exception, and looking at the bytecode, it becomes clearer why:
>>> import dis
>>> dis.dis(with_or_raise)
2 0 SETUP_EXCEPT 10 (to 12)
3 2 LOAD_FAST 0 (exc)
4 CALL_FUNCTION 0
6 RAISE_VARARGS 1
8 POP_BLOCK
10 JUMP_FORWARD 32 (to 44)
4 >> 12 DUP_TOP
14 LOAD_GLOBAL 0 (IndexError)
16 JUMP_IF_TRUE_OR_POP 20
18 LOAD_GLOBAL 1 (KeyError)
>> 20 COMPARE_OP 10 (exception match)
22 POP_JUMP_IF_FALSE 42
24 POP_TOP
26 POP_TOP
28 POP_TOP
5 30 LOAD_GLOBAL 2 (print)
32 LOAD_CONST 1 ('Got ya!')
34 CALL_FUNCTION 1
36 POP_TOP
38 POP_EXCEPT
40 JUMP_FORWARD 2 (to 44)
>> 42 END_FINALLY
>> 44 LOAD_CONST 0 (None)
46 RETURN_VALUE
So we can see, instruction 14 first loads the IndexError class onto the stack. Then it checks whether that value is True, which it is because of Python truthiness and finally jumps directly to instruction 20 where the exception match is done. Since instruction 18 was skipped, KeyError was never loaded onto the stack and therefore doesn't match.
I tried with Python 2.7 and 3.6, same result.
But then, why is it valid syntax? I imagine it being one of the following:
It's an artifact from a really old version of Python.
There is actually a valid use case for using or within an except clause.
It's simply a limitation of the Python parser which might have to accept any expression after the except keyword.
My vote is on 3 (given I saw some discussion about a new parser for Python) but I'm hoping someone can confirm that hypothesis. Because if it was 2 for example, I want to know that use case!
Also, I'm a bit clueless on how I'd continue that exploration. I imagine I would have to dig into CPython parser's source code but idk where to find it and maybe there's an easier way?
In except e, e can be any valid Python expression:
try1_stmt ::= "try" ":" suite
("except" [expression ["as" identifier]] ":" suite)+
...
[..] For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is “compatible” with the exception. An object is compatible with an exception if it is the class or a base class of the exception object or a tuple containing an item compatible with the exception.
https://docs.python.org/3/reference/compound_stmts.html#the-try-statement
The expression IndexError or KeyError yields the value IndexError. So this is equivalent to:
except IndexError:
...
You should use a n-tuple of types instead of a logical expression (which just returns the first non-false element):
def with_or_raise(exc):
try:
raise exc()
except (IndexError,KeyError):
print('Got ya!')
I'm getting an indention error in the following code:
28 def dropletExistsInSummaries( droplet ):
29 """
30 dropletExists() -- checks to see if a droplet's URL exists in the summary table, takes one argument
31 * droplet is the DID of the raindrop
32 """
33 log.debug( "entering" )
34 c2 = db.cursor()
35 d = ( droplet, )
36 did = 0
37 try:
38 c2.execute( 'SELECT did from summaries where did = ?', d )
39 did = c2.fetchone()[0]
40 except Exception, e:
41 log.error( "dropletExists query failed: %s", e )
42 if did > 0:
43 return did
44 else:
45 return 0
46
47
48 def summarizeDroplet( did, url ):
49 """
50 TODO: document this
:x
sodaphish#svr-lnx02:~/semanticrss$ ./tst.py
File "./tst.py", line 37
try:
^
IndentationError: unexpected indent
...which doesn't make any sense to me because I've checked to make sure everything is properly indented! I've stared at this for hours and am resigned to the fact that I need have help.
To be completely honest, I'm not entirely sure why I had to surround "droplet" with parens at line 35, and my guess is that's what's causing the problem, but I can't tell you with certainty that the issue is related to that.
For the record, I'm using Python 2.7.9.
Thanks in advance for any help!
Your function indent is three spaces, while the indentation of your try...except block is two spaces. Fix this and it should work.
PEP 8 recommends four spaces for indenting code, though.
I am writing a program to read the output of another program, read it line by line and put it in a list.
#!/usr/bin/python
import subprocess
def RECEIVE(COMMAND):
PROCESS = subprocess.Popen(COMMAND, stdout=subprocess.PIPE)
LINES = iter(PROCESS.stdout.readline, "")
for LINE in LINES:
RECARR = LINE.split()
print RECARR[14]
RECEIVE(["receivetest","-f=/dev/pcan32"])
The output from the receivetest program is:
19327481.401 receivetest: m s 0x0000000663 8 2f 00 42 02 00 e4 8a 8a
19327481.860 receivetest: m s 0x000000069e 8 00 1f 5e 28 34 83 59 1a
it is a constant stream of messages. When split, the list has a range of 14 because after splitting, to make sure, I used:
print len(RECARR)
This gave me an output of 14.
but whenever I try to print the last element:
print RECARR[14]
I get the following error:
file "./cancheck.py", line 10, in RECEIVE
print RECARR[14]
IndexError: list index out of range
This is caused by some erronious text that is printed at the top of the list, so I need some way of making sure that the program only reads in lines that start with
1234567.123
/^(.......\.\d{1,3}) (.*)$/
Any ideas?
Based on the sample data you provided, the length of RECARR is always 14.
14 is the size of the list, not the maximum index. To get the final element of the array, you can try RECARR[13] for this list, or RECARR[-1] in general.
The reason for this is that in Python, as in most programming languages, array indices are zero-based: the first element is accessed with RECARR[0], the second with RECARR[1], and so on. So, the 14th element (or the last one, in your case) would be accessed with RECARR[13].
So, your for loop would look something like this:
for LINE in LINES:
RECARR = LINE.split()
print RECARR[13] # or RECARR[-1]
Right everyone, it's a terrible workaround but I fixed the issue by working out that the only lines with exactly 14 elements are the lines I need so I fixed it by using the following
for LINE in LINES:
RECARR = LINE.split()
if(len(RECARR) == 14):
#do stuff
List indexes start from 0 and not 1. So
print RECARR[1]
prints the 2nd element and not the first. Thus to print the last element you have to use print RECARR[13] or negative index print RECARR[-1].
The lists in python can be depicted as
As you can see the last element can be accessed using either -1 or length of the list -1
An easier way to gauge the ranges is to put the indices before the cell. (Courtesy - Aristide)
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
You could have also done something similar to this:
try:
print RECARR[13]
except IndexError:
pass
This way you can easily handle the lines that are not long enough as well.
I have a 500x500 array and I am trying to write a variable called "coordinate" that will pick out each value and then apply it to a function but I keep getting the output,
AttributeError Traceback (most recent call last)
/home/graham/<ipython-input-17-cc6ce0649eda> in <module>()
31 pass
32
---> 33 finished_array = rand_array_color(rand_array)
34
35 finished_image = Image.fromarray(finished_array)
/home/graham/<ipython-input-17-cc6ce0649eda> in rand_array_color(rand_array)
23 from PIL import Image
24 for ii in numpy.nditer(rand_array):
---> 25 coordinate = tuple(map(int, rand_image[ii,:]))
26 if ii < 128:
27 print "false"
/usr/lib/python2.7/dist-packages/PIL/Image.pyc in __getattr__(self, name)
510 new['data'] = self.tostring()
511 return new
--> 512 raise AttributeError(name)
513
514 ##
AttributeError: __getitem__
Here is my code
from PIL import Image
from numpy import random
im = Image.open('/home/graham/Desktop/Experiment/gwarner/labeled_photos/photos/003030.png')
rand_array = numpy.random.randint(255, size=(500,500)).astype('uint8')
rand_image = Image.fromarray(rand_array)
def rand_array_color(rand_array):
from PIL import Image
for ii in numpy.nditer(rand_array):
coordinate = tuple(map(int, rand_image[ii,:]))
if ii < 128:
newvalue = rand_image.putpixel(coordinate(a,ii), im.getpixel(coordinate(a,ii)))
return newvalue
else:
pass
finished_array = rand_array_color(rand_array)
I've also been fiddling around with another version of coordinate,
coordinate = tuple(int(rand_array[ii,0]),int(rand_array[ii,1])
but it just returns,
NameError: name 'ii' is not defined
Can anyone tell me how to fix one of these or recommend another one that will work?
The reason you cannot get the iith row of rand_image using rand_image[ii,:] is because rand_image is a PIL Image object, and doesn't have the same indexing access that an array has. If you want to get the iith row, you must use rand_array[ii] (I've left off the trailing colon ,: isn't required)
This appears to be similar to your
another version of coordinate
which should work because you're using the array instead of the Image. My guess is that you've not replaced it in exactly the same place as the first version, perhaps somewhere outside of the for ii in ... loop, because ii is only properly defined within that loop.
As you've defined it, coordinate is not a function, it's a tuple of length 2. But you call it as a function when you write coordinate(a, ii). Rather, you probably just want to use coordinate there (I'm not sure what a is supposed to be.
The function .putpixel does not return anything, so that when you say:
newvalue = rand_image.putpixel(...)
newvalue will be None (the 'empty' object in python). Perhaps you want to do this:
rand_image.putpixel(...)
return rand_image
without setting the newvalue and trying to return it, but instead changing the pixel in the rand_image and returning the new rand_image.
As a side note, you should not call int() on a numpy array, instead, if you want the type of each element in the array to be int, you should either use .astype as you did above, or initiate it as an int in the first place. Once it starts as an int, it should stay that way unless you cast it somehow (which you haven't done in this script).
As a final note this process could probably be done a lot faster using numpy (not using pure python loops) but I'm not sure exactly what you're trying to do. If you edit your question to explain a little bit what you're trying to do so that I can read the code with some context, I could help. For example, what is a supposed to be in the newvalue = ... line?