Mainly Tech projects on Python and Electronic Design Automation.

Tuesday, February 02, 2021

Pythone'er abuses walrus

(... the operator, that is 😊).

 

I haven't used the new walrus operator, := much in code. This is an example of a working mis-use of it. 

A new task

I wrote a new task description on Rosetta Code, together with Python recursive and iterative solutions.

The gist of the task is:

  • Given a list of integers, >0, representing nesting levels, e.g. [1, 2, 4]
  • Generate a tree of those values, in order, in the stated depth of nesting. i.e. [1, [2, [[4]]]]

(Someone on Stackoverflow had that problem, and it seemed like it could form the basis of a good RC task).

Iterative solution

I posted the following code as my iterative solution.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def to_tree(x: list) -> list:
   nested = []
   stack = [nested]
   for this in x:
       while this != len(stack):
           if this > len(stack):
               innermost = []               # new level
               stack[-1].append(innermost)  # nest it
               stack.append(innermost)      # push it
           else: # this < stack:
               stack.pop(-1)
       stack[-1].append(this)

   return nested

It works using:

  1. len(stack) to capture nesting depth; and

  2. stack[-1] as a pointer into the active nest at that level; whilst

  3. nested accumulates the whole tree.

The walrus hack.

I was admiring lines seven to nine above and was initially rthinking about name innermost. It is a kind of temporary variable, but is instrumental in modifying stack. I thought: "could I do lines seven to eight in one statement"?

It is awkward as appends return None, but then the walrus operator came to my rescue and I produced the equivalent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def to_tree(x: list) -> list:
   nested = []
   stack = [nested]
   for this in x:
       while this != len(stack):
           if this > len(stack):
               stack.append(None if stack[-1].append(innermost:=[])
                            else innermost)
           else: # this < stack:
               stack.pop(-1)
       stack[-1].append(this)

   return nested

The one statement at lines seven and eight is equivalent. The whole expression is evaluated inside out:

  1. An empty list is created and assigned to name innermost.
  2. that same list is nested by appending it to the list at the top of the stack.
  3. The inner append always returns None which is False in the boolean context of the if condition.
  4. The else clause is always triggered, returning innermost - the newly created and nested list.
  5. That newly created and nested list is appended to the head of the stack.
This use of the walrus operator, a.k.a the assignment expression is bad Python. It is much harder to read and maintain than the previous code.

Other uses are Pythonic!

 

STOP PRESS!

Steven D'Aprano gives valuable insight on this in a comment here.


2 comments:

  1. Hmmm ...

    .append(innermost:=[])

    I have to admit, that syntax is really not good at all. I don't know what
    guido was thinking there ... python is already quite clean. Not every feature
    can or should be part of a programming language.

    ReplyDelete
    Replies
    1. I've come around a little from initial skepticism: It can be used well I haven't seen it being used badly in code I've read, (except for examples of bad usage such as this), so I am now trying to embrace it!

      Delete

Followers

Subscribe Now: google

Add to Google Reader or Homepage

Go deh too!

whos.amung.us

Blog Archive