[Tutor] all right students, what do we learn
Alan Gauld
alan.gauld at btinternet.com
Sun Nov 2 23:02:48 CET 2014
On 02/11/14 20:05, Clayton Kirkwood wrote:
>>> out that python doesn't seem to like an assignment in the overall if
>>> clause - error.
>>
>> Correct, the if statement requires an expression (specifically a boolean
>> expression). And assignments are not expressions.
>
> My thinking was that I was making a Boolean value:
>
>
> ]=[(reenter, key) for key in key_list if
>>> ((key in key_list0)) or (print("Error:", key, "not available, start
>>> again") and exec('reenter = True', ))]
The assignment does not make a value it assigns a value to a variable
but that value is not exposed in the code containing the assignment.
You can see that using the interpreter:
>>> result = exec('x=42')
>>> print (result)
None
>>> print(x)
42
>>>
You can see that the exec returned None to result.
The value of x was changed but the assignment itself
had no value. It is not a useful expression because
it will always return None which equates to false
in boolean terms.
Lets now look at what your conditional expression is doing:
(key in key_list0) or
( print("Error:", key, "not available, start again") and
exec('reenter = True'))
If key is in the list the evaluation stops there and the result plus the
current value of reenter are put in the output list.
If the key is not in the list the second part of the or is evaluated.
The print executes and returns the string it is given which is True.
So the second part of the AND is now evaluated which is the exec. The
exec always returns None or False.
So the if condition looks like:
False OR (True AND False)
which simplifies to: False or False
wjich is False.
So your if condition is only ever true when 'key in key_list0'
is true.
Note too that reenter will be true as soon as you hit a case where the
key is not in the list and will stay true thereafter, it will never go
back to false.
I suspect that's not the behaviour you are looking for.
> In the first case, key is in key_list0 so that is a True and we are finished
> for that key. In the other case, key is not in key_list0 so we go on past
> the or. I print which returns a non-False, ergo a True, and then I make an
> assignment which should be a True.
The exec assigns a value to reenter but returns None which is False.
> True. Assignments create a Boolean True (or should).
No they shouldn't. Assignments are not boolean expressions and cannot be
used as such
if x=42:
print(x)
results in a syntax error.
> The other issue is that I had the outside reenter set as true to start the
> for and turn it False so that the for won't re-occur unless I have a bad key
> and force reenter to be a True.
But the reenter inside the comprehension is an entirely different
reenter to the one outside. Your exec has no effect on it.
>>> Which I don't quite understand. The reason is because I set up the if
>>> statement to be True either way. With an a it would go thru and
>>> create the proper output.
But as shown above you dodn't, it is only true when the 'in' test is true.
> What I would expect from [('a', 'apple'), ('b', 'banana')] and entering a y
> Would be:
> [('a',True), ('y', False)]
>
> If I entered only 'y' I would expect
> [('y', False)] but this won't work because I can't use the '=' in
> the if clause even though it returns a True
OK, I got that but what are you trying to achieve in the context of your
problem? Is it to get a set of valid keys and values? In other words the
subset of your original data corresponding to the users input list? If
so I think there are far simpler ways to go about it, see below. I
suspect you are making the root solution more complex by the choice of
returning the true/false flag with each key.
>> "Keep asking the user for keys until they hit upon a list that is all
>> valid and create a list of corresponding values."
>>
>> Is that correct?
>
> Absotively
>
>>
>> If so I'd write it like this:
>>
>> prompt = 'Please enter space separated keys in the order you want: '
>> while True: # keep going round till we break
>> key_list = input(prompt).split()
>> if all(key in key_list0 for key in key_list):
>> break
>>
>> result = [(key, key_columns) for key in key_list]
>>
>> Which would give you a list containing each user key and its
>> corresponding value from key_list0.
>
> Yes, this approaches what my goal is, but it doesn't indicate which if any
> bad keys ([pair[0]) are there, ergo, wanting to return a False if the key
> didn't exist in both lists. Your snippet definitely removes all bad keys,
> however.
Yes, that's the point, it only allows good keys through so you don't
need to collect the bad keys. If you wanted to tell the user which keys
were invalid then modify the loop code to report the faulty one.
prompt = 'Please enter space separated keys in the order you want: '
while True: # keep going round till we break
key_list = input(prompt).split()
bad_keys = [key in key_list0 for key not in key_list]
if not bad_keys:
break
else: print("The following keys were invalid: ",bad_keys)
You could even put that in a function:
def get_valid_keys():
prompt = 'Please enter space separated keys in the order you want: '
while True: # keep going round till we break
key_list = input(prompt).split()
bad_keys = [key in key_list0 for key not in key_list]
if not bad_keys:
return key_list
else: print("The following keys were invalid: ",bad_keys)
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos
More information about the Tutor
mailing list