Why is this a valid statement in Python?
"Guido"
This tripped me up with a multi-line string where I did not properly use parens:
# BAD
message = "Guido"
" van Rossum"
# GOOD
message = ("Guido"
" van Rossum")
Is it purely for the repl or is there some other reasoning for it?
Expressions are statements in Python (and most other imperative languages) for several good reasons:
What if a function, like foo() does something useful but also returns a value? foo() would be an invalid statement if the language didn't allow us to implicitly discard the return value.
Docstrings! They are just strings that happen to be the first statement of a module/class/function, so no special syntax was needed to support them.
In general, it's hard for the interpreter to determine whether an expression might have side effects. So it's been designed to not even try; it simply evaluates the expression, even if it's a simple constant, and discards the result.
To check for such mistakes as you mentioned, and many others, pylint can be helpful. It has a specific warning for this very case. However, it seems to not catch the mistake in your exact example code (using PyLint version 2.4.4); might be a bug.
Related
Extremely basic question that I don't quite get.
If I have this line:
my_string = "how now brown cow"
and I change it like so
my_string.split()
Is this acceptable coding practice to just straight write it like that to change it?
or should I instead change it like so:
my_string = my_string.split()
don't both effectively do the same thing?
when would I use one over the other?
how does this ultimately affect my code?
always try to avoid:
my_string = my_string.split()
never, ever do something like that. the main problem with that is it's going to introduce a lot of code bugs in the future, especially for another maintainer of the code. the main problem with this, is that the result of this the split() operation is not a string anymore: it's a list. Therefore, assigning a result of this type to a variable named my_string is bound to cause more problems in the end.
The first line doesn't actually change it - it calls the .split() method on the string, but since you're not doing anything with what that function call returns, the results are just discarded.
In the second case, you assign the returned values to my_string - that means your original string is discarded, but my_string no refers to the parts returned by .split().
Both calls to .split() do the same thing, but the lines of your program do something different.
You would only use the first example if you wanted to know if a split would cause an error, for example:
try:
my_string.split()
except:
print('That was unexpected...')
The second example is the typical use, although you could us the result directly in some other way, for example passing it to a function:
print(my_string.split())
It's not a bad question though - you'll find that some libraries favour methods that change the contents of the object they are called on, while other libraries favour returning the processed result without touching the original. They are different programming paradigms and programmers can be very divided on the subject.
In most cases, Python itself (and its built-in functions and standard libraries) favours the more functional approach and will return the result of the operation, without changing the original, but there are exceptions.
What's the design thinking behind this?
To me it's easier to do something like
if string.index(substring) > -1:
# do stuff
than trying to catch an exception. If the substring is not found, at least your program doesn't break.
Someone told me 'returning -1 is a bad pattern'. Why is that?
What is the Pythonic way for checking substring?
str.index() throws an exception; you were perhaps thinking of the str.find() method instead:
if string.find(substring) > -1:
The str.index() documentation explicitly states this:
Like find(), but raise ValueError when the substring is not found.
However, the correct way to test for substring membership is to use in:
if substring in string:
Because this way at least the return type of the function is fixed. Also your example is not pythonic, it should read:
if str in string:
# do stuff
Python operates under the principle of "easier to ask for forgiveness than permission" (EAFP), as explained in an answer by Sven Marnach. It allows the code for the common path to be kept together, making the logic easier to understand without inline error handling cluttering the flow. And in a program that uses import threading for non-blocking I/O, reading the variable only once makes time-of-check-to-time-of-use (TOCTTOU) bugs less likely than in look-before-you-leap style that some other languages encourage.
The major drawback of EAFP is that Python's syntax for exception handling doesn't mesh well with functional programming style. You can't catch exceptions for individual elements in the iterable input to a generator expression without defining and naming a function.
Can inputting and checking be done in the same line in python?
Eg) in C we have
if (scanf("%d",&a))
The above statement if block works if an integer input is given. But similarly,
if a=input():
Doesn't work in python. Is there a way to do it?
No, Python can't do assignment as part of the condition of an if statement. The only way to do it is on two lines:
a=input()
if a:
// Your code here
pass
This is by design, as it means that assignment is maintained as an atomic action, independent of comparison. This can help with readability of the code, which in turn limits the potential introduction of bugs.
You can't do it. This was a deliberate design choice for Python because this construct is good for causing hard to find bugs.
see #Jonathan's comment on the question for an example
In Python, assert is a statement, and not a function. Was this a deliberate decision? Are there any advantages to having assert be a statement (and reserved word) instead of a function?
According to the docs, assert expression1, expression2 is expanded to
if __debug__:
if not expression1: raise AssertionError(expression2)
The docs also say that "The current code generator emits no code for an assert statement when optimization is requested at compile time." Without knowing the details, it seems like a special case was required to make this possible. But then, a special case could also be used to optimize away calls to an assert() function.
If assert were a function, you could write:
assert(some_long_condition,
"explanation")
But because assert is a statement, the tuple always evaluates to True, and
you get
SyntaxWarning: assertion is always true, perhaps remove parentheses?
The correct way to write it is
assert some_long_condition, \
"explanation"
which is arguably less pretty.
Are there any advantages to having assert be a statement (and reserved word) instead of a function?
Cannot be reassigned to a user function, meaning it can be effectively disabled at compile time as #mgilson pointed out.
The evaluation of the second, optional parameter is deferred until if/when the assertion fails. Awkward to do that with functions and function arguments (would need to pass a lambda.) Not deferring the evaluation of the second parameter would introduce additional overhead.
One of the wonderful things about assert in python and in other languages (specifically C) is that you can remove them to optimize your code by just adding the correct #define (optionally on the commandline with any compiler I've ever used) or optimization flags (-O in python). If assert became a function, this feature would be impossible to add to python as you don't know until runtime whether you have the builtin assert function or user-defined function of the same name.
Also note that in python, function calls are reasonably expensive. Replacing inline with the code if __debug__: ... is probably a lot more efficient than doing a function call which could be significant if you put an assert statement in a performance critical routine.
In addition to the other answers (and sort of off-topic) a tip. To avoid the use of backslashes you can use implicit line joining inside parenthesis. ;-)
Instead of:
assert some_long_condition, \
"explanation"
You could write:
assert some_long_condition, (
"explanation")
I am no expert in Python, but I believe performance is one of the biggest reason.
if we have assert(expression, explanation) as function, if expression is expensive to evaluate, even we are in non-debug mode, Python needs to evaluate both expression to pass it to the assert function.
By expanding the assert, the expression and explanation statement is in fact not evaluated unless they are really needed (when debug evaluates to true). I believe it is critical if we want to make assert not affecting performance when not necessary (i.e. no performance hit in production system).
Is the following code bad practice?
for i in some_values:
do_whatever(i)
do_more_things(i)
Somehow, it feels to me like the variable i should remain in the scope to the block inside the for-loop. However python 2.7 lets me reuse it after the loop.
Does python officially supports that feature, or am I abusing the language?
Yes, it's official:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
> The target list is not deleted when the loop is finished
http://docs.python.org/reference/compound_stmts.html#for
Note that a target list after for is far more than just a variable:
for some_list[blah] in...
for some_object.foo in...
for a[:n] in ...:
etc. These things cannot simply disappear after the loop.
Python can feel a bit special when it comes to scoping if you are coming from languages like C or Java. As previous answer says, the code is absolutely valid but I would recommend against it. It creates not particularly readable code and, furthermore, if some_values turns out to be empty, there will be an exception raised on the last line of the code.
So answer to your question is - yes, it is officially supported but in most cases it is not recommended strategy.
Interesting discussion can be found here and also local discussion on SO.
You can use this technique to scan a list for items matching some criteria:
for item in iter:
if interesting(item):
break
else:
raise ValueError('iter is boring.')
handle(item)
Just like #petr said, it sound unnatural. Not because it's allowed that it's natural or you have to use it.
I rather have something like this, although it may not apply to the logic with a break use-case:
for i in some_values:
do_whatever(i)
else:
do_more_things(i)
But this still raise NameError if some_values evaluate to empty, but sounds clearer. It does not give the clear readability of an inner scope but the indentation may suggests it.
But as other said, to answer to the specific OP's question, yes, it's legal.
That's not a feature. As you wrote the variable remains in the scope. It's normal interpreter behavior.