`pass` keyword to mark end of indented code block - python

I have recently noticed that some people mark the end of indented code blocks with the pass keyword, such as:
def f():
for i in range(10):
do_something(i)
pass
pass
I don't understand why. Are there any advantages?
I know the pass keyword does nothing and it is the equivalent of { } in other languages. My question is more related to a convention. For example, maybe people like to have something marking the end of a long code block.

Do you think Python's indention-sensitive grammar is harmful?
If your answer is "no",
then using pass to mark an end does nothing but clutter the cleanness
brought in by Python's indention sensitive grammar.
If your answer is "yes",
then using pass to mark an end is a workaround for the ambiguity
brought in by Python's indention sensitive grammar.
In Python, there is no {} and end, but semantic white spaces.
For example, consider the following Ruby code:
def f
for i in 0...10
i = i * 2
print(i)
end
end
And the equivalent Python code:
def f():
for i in range(10):
i = i * 2
print(i)
With one wrong keystroke (TAB):
def f():
for i in range(10):
i = i * 2
print(i)
The above code is also valid.
To avoid this kind of mistakes, we can use pass for end in Python:
def f():
for i in range(10):
i = i * 2
print(i)
pass
pass
With one wrong keystroke (TAB):
def f():
for i in range(10):
i = i * 2
print(i)
pass
pass
Python will refuse to work:
IndentationError: unexpected indent
However, python will not always catch unintended indentation even with pass.
Suppose we intend to write:
def g():
for i in range(10):
i = i * 2
pass
print(i)
pass
With one wrong keystroke (TAB):
def g():
for i in range(10):
i = i * 2
pass
print(i)
pass
Python will not refuse to work.
But using pass still has two advantages:
It still provides visual hint.
If you think pass as the last clause of an indented block,
print(i) looks weird to you in the above code.
A decent editor/IDE will indent correctly if you typed pass.
For the second pass,
if f() is a top-level function,
and your code adheres to PEP8:
Surround top-level function and class definitions with two blank lines.
You may omit the second pass.
But PEP8 also said:
Extra blank lines may be used (sparingly)
to separate groups of related functions.
Thus I prefer pass.

There is no advantage. If the function has a body at all, adding pass does nothing. It doesn't even do anything if there is no body, except to help the parser know that the empty body was intentional.
In real-world code, it's usually better to use a docstring than pass to denote deliberately-empty code:
class MyExtraException(Exception):
"""Just another exception"""

Is there any advantages?
No.
Placing pass at the end of non-empty code blocks like that just wastes lines. Remember that pass is a do-nothing placeholder in Python; it should only be used when you need to fill in an empty code block.
If you would like some examples of when to use pass, see this SO question as well as this one.

Related

What is the difference between Pass and None in Python

I would personally like to know the semantic difference between using Pass and None. I could not able to find any difference in execution.
PS: I could not able to find any similar questions in SO. If you find one, please point it out.
Thanks!
pass is a statement. As such it can be used everywhere a statement can be used to do nothing.
None is an atom and as such an expression in its simplest form. It is also a keyword and a constant value for “nothing” (the only instance of the NoneType). Since it is an expression, it is valid in every place an expression is expected.
Usually, pass is used to signify an empty function body as in the following example:
def foo():
pass
This function does nothing since its only statement is the no-operation statement pass.
Since an expression is also a valid function body, you could also write this using None:
def foo():
None
While the function will behave identically, it is a bit different since the expression (while constant) will still be evaluated (although immediately discarded).
In simple terms, None is a value that you can assign to a variable that signifies emptiness. It can be useful as a default state:
a = None
def f():
a = 5
f()
pass is a statement that is like a nop. It can be useful when you are defining function stubs, for instance:
def f():
pass
In C-like languages, you would be able to define empty functions by simply putting nothing between the braces void f() { }, but since Python uses indentation instead of braces to define blocks, you must put something in the body, and pass is the idiomatic thing to put there.
That's absolute difference between pass and None
The pass (without upper case P):
Because python be the indent base language, so if you define a new method, you should have some code after that.
def method_a():
some_thing = 1 # Have to do some thing
If not, an exception should be raised so you could use the pass keyword for hacks this problem.
def method_a():
pass # Do nothing
The None:
So very different, the None keyword has a little bit same to the null keywords from another language like Java or C. That may be the empty data or not assign data like that.
[] == None
null == None
() == None
...

When is Python code between """ """ executed? [duplicate]

Let's say, I've got a function like this:
def myFunc():
# useful function to calculate stuff
This will produce an indentation error, unless I add pass:
def myFunc():
# useful function to calculate stuff
pass
However, if I replace a comment with docstring, no pass is necessary:
def myFunc():
"""useful function to calculate stuff"""
This seems like an odd feature as neither of these are used in the program, as far as I know. So, why does it behave like this?
A comment is outright ignored by the interpreter, so omitting a block after an indent is a syntax error. However, a docstring is a real Python object--at its most basic, a literal str. A lone expression is a valid block of code:
'This is a string. It is a valid (though pretty useless) line of Python code.'
In the case of docstrings in particular, there's also some additional functionality going on, such as being used to set the __doc__ attribute.
>>> def myFunc():
... '''MyDocString'''
...
>>> print(myFunc.__doc__)
MyDocString
Note that this also works for classes:
>>> class MyClass(object):
... '''MyClassDocString'''
...
>>> print(MyClass.__doc__)
MyClassDocString
A docstring isn't just a comment. It actually has meaning to the interpreter. In the case with a docstring, you could do myFunc.__doc__ and actually get your docstring back (In the other case with a pass, the result myFunc.__doc__ would be None).
In other words, you are actually adding some code to the function body to modify it's behavior (in some circumstances), so no pass is necessary.

Commented block indentation in python

Is there a way to avoid "expected indent block" errors in Python without adding pass to a function?
def exclamation(s):
# s += "!!!"
# return s
print exclamation("The indented horror")
The above code results in an error on line 5. Yes, remove the comments and the code works fine. However, in debugging stuff I often find myself in a similar situation. Is this just a hang-up of the off-side rule and something I need to get used to or are there ways around this?
There has to be something within your function definition to avoid a SyntaxError.
The issue is that the interpreter will effectively ignore comments during parsing, and so while to a human it might look like something is there, to the parser it is empty.
As jonrsharpe has pointed out in a comment, you can use docstrings to "comment out" your code and have it still work. This is because the docstring is, in effect, a normal string. As such this will be parsed and won't cause a SyntaxError. To take your example code it would look like:
def exclamation(s):
'''s += "!!!"
return s'''
# This should print None as nothing is now returned from the func
print(exclamation("The indented horror"))

Invalid syntax error in Python

I'm starting Comp Sci courses in Uni this coming fall (starting with zero programming knowledge), so I'm just starting to play around programming. I'm following a book and tried copy-pasting some code - but it doesn't work. Here's what I tried:
>>> def function(x):
return x+2
function(2)
SyntaxError: invalid syntax
The word "function" was highlighted. I'm confused because the very same example is used in the book and it appears to work but then I get that error on my end. What's going on here?
You need to separate the function definition from its execution. Also, Python is sensitive to whitespace at the beginning of lines. Try this (exactly):
def function(x):
return x+2
function(2)
or, in one line (which you should not do; see the style guidelines):
def function(x): return x+2; function(2)
or, in the Python shell:
>>> def function(x):
return x+2
>>> function(2)
4
Note the blank line between the function definition and its use. After you define the function, hit enter once to get the prompt back.
I'm assuming you meant to put Python in the title. Python has interesting syntax rules in that it actually counts white space as meaningful when parsing the program. What I mean is that having extra space, newlines, or tabs, etc. actually changes the meaning of the program. Double check the book example and make sure you have the exact same (tabs, new lines, and all) syntax written. It may look closer to this:
def f(x):
return x + 2
note the new line and tab. To call this function, on a separate line say:
f(5)
or replace 5 with whatever parameter you want.
edit:
so the full script should be:
def f(x):
return x + 2
f(2)
Try this:
def function(x):
return x+2
function(5)
In python, indentations are important. They are the {} of the python world.
You actually do not need to add extra whitespace before function(5) because python knows not to include it in the function definition because it is not indented. It is still good practice to add the extra blank line, but it is not strictly necessary.
This is for the users using Python 2.6.6 and IDLE 2.6.6.
Since Python interpreter is very much sensitive to whitespace and indentations, we need to separate the function declaration from the execution.
What you must be doing:
>>> def square(input):
output=input*input
return output
print square(5)
Output: SyntaxError: invalid syntax
Correct way to do it:
>>> def square(input):
output=input*input
return output
>>> print square(3)
9

Can I be warned when I used a generator function by accident

I was working with generator functions and private functions of a class. I am wondering
Why when yielding (which in my one case was by accident) in __someFunc that this function just appears not to be called from within __someGenerator. Also what is the terminology I want to use when referring to these aspects of the language?
Can the python interpreter warn of such instances?
Below is an example snippet of my scenario.
class someClass():
def __init__(self):
pass
#Copy and paste mistake where yield ended up in a regular function
def __someFunc(self):
print "hello"
#yield True #if yielding in this function it isn't called
def __someGenerator (self):
for i in range(0, 10):
self.__someFunc()
yield True
yield False
def someMethod(self):
func = self.__someGenerator()
while func.next():
print "next"
sc = someClass()
sc.someMethod()
I got burned on this and spent some time trying to figure out why a function just wasn't getting called. I finally discovered I was yielding in function I didn't want to in.
A "generator" isn't so much a language feature, as a name for functions that "yield." Yielding is pretty much always legal. There's not really any way for Python to know that you didn't "mean" to yield from some function.
This PEP http://www.python.org/dev/peps/pep-0255/ talks about generators, and may help you understand the background better.
I sympathize with your experience, but compilers can't figure out what you "meant for them to do", only what you actually told them to do.
I'll try to answer the first of your questions.
A regular function, when called like this:
val = func()
executes its inside statements until it ends or a return statement is reached. Then the return value of the function is assigned to val.
If a compiler recognizes the function to actually be a generator and not a regular function (it does that by looking for yield statements inside the function -- if there's at least one, it's a generator), the scenario when calling it the same way as above has different consequences. Upon calling func(), no code inside the function is executed, and a special <generator> value is assigned to val. Then, the first time you call val.next(), the actual statements of func are being executed until a yield or return is encountered, upon which the execution of the function stops, value yielded is returned and generator waits for another call to val.next().
That's why, in your example, function __someFunc didn't print "hello" -- its statements were not executed, because you haven't called self.__someFunc().next(), but only self.__someFunc().
Unfortunately, I'm pretty sure there's no built-in warning mechanism for programming errors like yours.
Python doesn't know whether you want to create a generator object for later iteration or call a function. But python isn't your only tool for seeing what's going on with your code. If you're using an editor or IDE that allows customized syntax highlighting, you can tell it to give the yield keyword a different color, or even a bright background, which will help you find your errors more quickly, at least. In vim, for example, you might do:
:syntax keyword Yield yield
:highlight yield ctermbg=yellow guibg=yellow ctermfg=blue guifg=blue
Those are horrendous colors, by the way. I recommend picking something better. Another option, if your editor or IDE won't cooperate, is to set up a custom rule in a code checker like pylint. An example from pylint's source tarball:
from pylint.interfaces import IRawChecker
from pylint.checkers import BaseChecker
class MyRawChecker(BaseChecker):
"""check for line continuations with '\' instead of using triple
quoted string or parenthesis
"""
__implements__ = IRawChecker
name = 'custom_raw'
msgs = {'W9901': ('use \\ for line continuation',
('Used when a \\ is used for a line continuation instead'
' of using triple quoted string or parenthesis.')),
}
options = ()
def process_module(self, stream):
"""process a module
the module's content is accessible via the stream object
"""
for (lineno, line) in enumerate(stream):
if line.rstrip().endswith('\\'):
self.add_message('W9901', line=lineno)
def register(linter):
"""required method to auto register this checker"""
linter.register_checker(MyRawChecker(linter))
The pylint manual is available here: http://www.logilab.org/card/pylint_manual
And vim's syntax documentation is here: http://www.vim.org/htmldoc/syntax.html
Because the return keyword is applicable in both generator functions and regular functions, there's nothing you could possibly check (as #Christopher mentions). The return keyword in a generator indicates that a StopIteration exception should be raised.
If you try to return with a value from within a generator (which doesn't make sense, since return just means "stop iteration"), the compiler will complain at compile-time -- this may catch some copy-and-paste mistakes:
>>> def foo():
... yield 12
... return 15
...
File "<stdin>", line 3
SyntaxError: 'return' with argument inside generator
I personally just advise against copy and paste programming. :-)
From the PEP:
Note that return means "I'm done, and have nothing interesting to
return", for both generator functions and non-generator functions.
We do this.
Generators have names with "generate" or "gen" in their name. It will have a yield statement in the body. Pretty easy to check visually, since no method is much over 20 lines of code.
Other methods don't have "gen" in their name.
Also, we do not every use __ (double underscore) names under any circumstances. 32,000 lines of code. Non __ names.
The "generator vs. non-generator" method function is entirely a design question. What did the programmer "intend" to happen. The compiler can't easily validate your intent, it can only validate what you actually typed.

Categories