On 31/12/2017 17:06, Chris Angelico wrote:
On Mon, Jan 1, 2018 at 3:55 AM, bartc <b...@freeuk.com> wrote:
The suggestion was to use them to avoid gotos.  If duplicating is a good
idea (and it's a hard line to draw) then we are not talking about the
same cases.  Given the choice of "dragging in named functions" and
dragging in named blocks and gotos, I would choose the functions every
time.


The blocks don't need to be dragged; they are already in place!

It's funny because in c.l.c you're always advocating keep declarations as
close to the point of use as possible. Here you appear to be saying the
opposite: taking code away from the primary point of use.

I don't understand the issue here. All you need to do is add a "def"
statement header in front of the block of code. And maybe indent it
further, although if you're unifying "if/elif" subtrees, that'll
cancel out the indentation level change. The block of code stays at or
near its first use.

You'll need to give an example I think. Suppose I start with this:

def fn(a):
    if a==1:
        print ("One")
        print ("Two")
        print ("Three")
    elif a==2:
        print ("Four")
    else:
        print ("Other")
        print ("One")
        print ("Two")
        print ("Three")

I want to share the lines that print One Two Three, so I create an inline function, defined as close as possible to the original code:

def fn2(a):
    if a==1:
        def F123():
            print ("One")
            print ("Two")
            print ("Three")
        F123()
    elif a==2:
        print ("Four")
    else:
        print ("Other")
        F123()

However, if I call this with fn2(3), it says that variable F123 has not been assigned.

(I'm not sure what overheads are associated with nested functions. Presumably its byte-code is done once, but is there any other setup of F123 associated with each call of fn2()? Even when a==2 so that F123() is not called?

A brief test [not using print()] showed it was a little slower having F123 inside fn2() - and outside the if-statement to make it work - than having F123 outside. And having to call F123() anyway instead of just having the inline code makes it a little slower too.

Although this would need to be balanced by the cost of the alternative, whether a goto or whatever.)

Note also that a goto, and a function call, don't do the same thing. The function will return, the goto won't. In my example all paths will return, in others this will have to be taken care of.

--
bartc












Don't forget that after turning a block into a def-function in-place, it will need to be followed by a call to it:

  if X:
     A
     B
     C
  elif ...
  else:
     A
     B
     C

This becomes:

   if X:
      def F():
         A
         B
         C
      F()
   elif...
   else
      F()

(Is the def statement executed once during byte-code compilation? Or can it give different result each time depending on what globals are visible within F? Will there at least be a set-up overhead for F each time


Note that calling a local function is not quite a drop-in replacement for


Once again, Bart, you're scorning something that you don't have much
(any?) experience with. Look at how the feature is used before you
hate on it.

ChrisA


--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to