What exactly is "pass"? What should it be?

J

John Ladasky

Hi folks,

I'm trying to write tidy, modular code which includes a long-running process. From time to time I MIGHT like to check in on the progress being made by that long-running process, in various ways. Other times, I'll just want to let it run. So I have a section of code which, generally, looks like this:

def _pass(*args):
pass

def long_running_process(arg1, arg2, arg_etc, report = _pass):
result1 = do_stuff()
report(result1)
result2 = do_some_different_stuff()
report(result2)
result3 = do_even_more_stuff()
report(result3)
return result3

This does what I want. When I do not specify a report function, the process simply runs. Typically, when I do supply a report function, it would print something to stdout, or draw an update through a GUI.

But this approach seems a tad cumbersome and unPythonic to me, particularlythe part where I define the function _pass() which accepts an arbitrary argument list, and does nothing but... pass.

This has led me to ask the question, what exactly IS pass? I played with the interpreter a bit.

IDLE 2.6.6 ==== No Subprocess ====SyntaxError: invalid syntax

So, pass does not appear to be a function, nor even an object. Is it nothing more than a key word?

And would there be any merit to having some syntactic sugar which allows pass to behave like the _pass() function I wrote, if it were called?

As you can see, I'm programming in Python 2.6. I don't know whether pass is handled differently in Python 3.
 
C

Chris Rebert

Hi folks,

I'm trying to write tidy, modular code which includes a long-running process.  From time to time I MIGHT like to check in on the progress beingmade by that long-running process, in various ways.  Other times, I'll just want to let it run.  So I have a section of code which, generally, looks like this:

def _pass(*args):
   pass

def long_running_process(arg1, arg2, arg_etc, report = _pass):
   result1 = do_stuff()
   report(result1)
   result2 = do_some_different_stuff()
   report(result2)
   result3 = do_even_more_stuff()
   report(result3)
   return result3

This does what I want.  When I do not specify a report function, theprocess simply runs.  Typically, when I do supply a report function, it would print something to stdout, or draw an update through a GUI.

But this approach seems a tad cumbersome and unPythonic to me, particularly the part where I define the function _pass() which accepts an arbitrary argument list, and does nothing but... pass.

Seems fine to me (good use of the null object pattern), although I
might define _pass() to instead take exactly 1 argument, since that's
all you ever call report() with in your example.
This has led me to ask the question, what exactly IS pass?  I playedwith the interpreter a bit.

IDLE 2.6.6      ==== No Subprocess ====
SyntaxError: invalid syntax

So, pass does not appear to be a function, nor even an object.  Is it nothing more than a key word?

Correct:
http://docs.python.org/reference/simple_stmts.html#pass
http://docs.python.org/reference/lexical_analysis.html#keywords

Cheers,
Chris
 
D

Dominic Binks

Seems fine to me (good use of the null object pattern), although I
might define _pass() to instead take exactly 1 argument, since that's
all you ever call report() with in your example.
It is a keyword that can appear in a position where a statement is
required by the grammar but there is nothing to do. For example if ..
then .. else .. where nothing happens in the else condition is effectively:

if <condition>:
<then-part>
else:
pass

Bourne shell has a similar construct with the colon statement :

Another python example is where you need to catch an exception (or all
exceptions but don't actually care about what they are)

try:
<european swallows>
except:
pass
 
D

Dennis Lee Bieber

I'm trying to write tidy, modular code which includes a long-running process. From time to time I MIGHT like to check in on the progress being made by that long-running process, in various ways. Other times, I'll just want to let it run. So I have a section of code which, generally, looks like this:

def _pass(*args):
pass
This is the equivalent of

def _pass(*args):
return None

(functions with no explicit return statement implicitly return None)
def long_running_process(arg1, arg2, arg_etc, report = _pass):
result1 = do_stuff()
report(result1)

So this is a call to a function that just returns a None, which is
dropped by the interpreter...
 
J

John Ladasky

Seems fine to me (good use of the null object pattern), although I
might define _pass() to instead take exactly 1 argument, since that's
all you ever call report() with in your example.

Oops, I over-simplified the calls to my report() function. The truth is that report() can accept a variable argument list too.
 
J

John Ladasky

Seems fine to me (good use of the null object pattern), although I
might define _pass() to instead take exactly 1 argument, since that's
all you ever call report() with in your example.

Oops, I over-simplified the calls to my report() function. The truth is that report() can accept a variable argument list too.
 
J

John Ladasky

This is the equivalent of

def _pass(*args):
return None

(functions with no explicit return statement implicitly return None)

OK, that works for me, and now I understand.

One of my questions was: would there be any merit to having the Python "pass" token itself defined exactly as _pass() is defined above?
 
J

John Ladasky

This is the equivalent of

def _pass(*args):
return None

(functions with no explicit return statement implicitly return None)

OK, that works for me, and now I understand.

One of my questions was: would there be any merit to having the Python "pass" token itself defined exactly as _pass() is defined above?
 
C

Chris Angelico

One of my questions was: would there be any merit to having the Python "pass" token itself defined exactly as _pass() is defined above?

No, there wouldn't. The Python 'pass' statement is a special statement
that indicates a lack of anything to execute; a dummy function call
isn't this. What I would kinda like to see, though, is function
versions of many things. Your basic operators exist in the 'operator'
module, but the syntax is rather clunky; for comparison, Pike has
beautifully simple (if a little cryptic) syntax: back-tick followed by
the operator itself, very similar to the way C++ does operator
overloading.

In Python 2, back-tick has a special meaning. In Python 3, that
meaning is removed. Is the character now available for this
"function-version" syntax?

ChrisA
 
C

Chris Rebert

No, there wouldn't. The Python 'pass' statement is a special statement
that indicates a lack of anything to execute; a dummy function call
isn't this. What I would kinda like to see, though, is function
versions of many things. Your basic operators exist in the 'operator'
module, but the syntax is rather clunky; for comparison, Pike has
beautifully simple (if a little cryptic) syntax: back-tick followed by
the operator itself, very similar to the way C++ does operator
overloading.

In Python 2, back-tick has a special meaning. In Python 3, that
meaning is removed. Is the character now available for this
"function-version" syntax?

Negative. I know this from personal experience.

Things that will Not Change in Python 3000
(http://www.python.org/dev/peps/pep-3099/ ):
"No more backticks."

Cheers,
Chris R.
 
A

alex23

If you call your dummy function something else, it may help
readability/self-documentation too.

Or replace the pass with a docstring for the same effect:

def silent(*args):
"""Null Object to repress reporting"""
 
S

Steven D'Aprano

One of my questions was: would there be any merit to having the Python
"pass" token itself defined exactly as _pass() is defined above?

No.

The pass statement compiles to nothing at all. Your _pass() function
compiles to a function object, which needs to be looked up at run time,
then called, all of which takes time and memory.

To satisfy the compiler, but do nothing, the pass statement should stay a
statement. When you need a "do nothing" function, either define one (two
lines) in your application, or use a lambda in place (lambda *args:
None). Either way, it is too trivial to be a built-in.

By the way, to answer your earlier question "what is pass?", you could do
this in the interactive interpreter:

help("pass")
 
T

Thomas Rachel

Am 18.11.2011 05:34 schrieb Dennis Lee Bieber:
So this is a call to a function that just returns a None, which is
dropped by the interpreter...

I'm not sure about this. I think, the call will be executed, but the
callee will return immediately. It is different from call being dropped.

Another optimized alternative could be to do

def long_running_process(arg1, arg2, arg_etc, report=None):
result1 = do_stuff()
if report: report(result1)

but I think that is too low benefit at the cost of too much readability.

Such a function call is

2 0 LOAD_FAST 0 (a)
3 POP_JUMP_IF_FALSE 16
6 LOAD_FAST 0 (a)
9 CALL_FUNCTION 0
12 POP_TOP
13 JUMP_FORWARD 0 (to 16)

3 >> 16 ...

as opposed to just

2 0 LOAD_FAST 0 (a)
3 CALL_FUNCTION 0
6 POP_TOP

with a call target of

1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE

I don't think that a call is sooo expensive that it would make any
noticeable difference.


Thomas

BTW: Sorry, Dennis, for the private mail - I am incapable to use
Thunderbird correctly :-(
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,260
Messages
2,571,039
Members
48,768
Latest member
first4landlord

Latest Threads

Top