[–] [S] 3 points 1 month ago* (last edited 1 month ago) (2 children)

There is one important difference between a |= b and a = a | b, that is one part that makes this exercise difficult. See the dictionary docs (https://docs.python.org/3/builtins/stdtypes.html#dict):

d |= other Update the dictionary d with keys and values from other, which may be either a mapping or an iterable of key/value pairs. The values of other take priority when d and other share keys. Added in version 3.9.

Pick your answer and check the Solution link.

The zen of Python lies unless you're Dutch. I'm Dutch and when I look out of my office I see the CWI where Guido wrote the original Python versions back in the day, see "Python the documentory" on YouTube.

  • source
  • parent
  • context
  • [–] [S] 3 points 1 month ago* (4 children)

    I think the confusion comes from a += b being equivalent to a = a + b for immutable types, so some people generalize that incorrectly to mutable types too. Otherwise I think it's pretty clear a += b mutates a, and a = a + b first computes a + b and then reassigns that to a so that its identity changes, just like in c = a + b.

    If you implement these operations in a class you have to implement each dunder, __iadd__(self, other) and __add__(self, other) separately, same thing in C++.

  • source
  • parent
  • context
  • [–] [S] 3 points 1 month ago (10 children)

    If you don't want mutability you have to go to a pure functional language like Haskell, but then you have to copy a big list every time you make a change. There are ways to optimize copying by secretly sharing data behind the scene but you pay a performance price in some way. Then again, Python is slow and has mutability but popular for other reasons.

  • source
  • parent
  • context
  •  

    A hard exercise to help build the right mental model for Python data.

    The “Solution” link visualizes execution and reveals what’s actually happening using 𝗺𝗲𝗺𝗼𝗿𝘆_𝗴𝗿𝗮𝗽𝗵: https://github.com/bterwijn/memory_graph

     

    In last week’s post we showed that a Python for-loop works through the Iterator Protocol.

    This same protocol also enables values to be produced lazily.

    In this new Lazy Evalution Example we show one sink reading values from five different sources:

    • source1: eagerly returns all values by list
    • source2: lazily by generator function using yield
    • source3: eagerly by list comprehension
    • source4: lazily by generator expression
    • source5: lazily by iterator protocol

    The same for-loop consumes all five sources. The eager sources produce all values before the sink starts consuming them. In the lazy sources producer and consumer take turns:

    • produce → consume → produce → consume → …

    Each value is produced only when the for-loop requests it.

    Generator functions and generator expressions are concise, readable ways to create lazy iterables. The final source makes their underlying mechanism explicit:

    • iter() obtains an iterator.
    • next() requests the next value.
    • StopIteration signals that no values remain.

    This clearly shows that generators achieve lazy iteration by implementing Python’s Iterator Protocol.

     

    Yesterday my exercise got downvoted, probably because its point was unclear. I'd like to try again with this reworked exercise. Hope you'll like this one better.

    • Solution
    • Explanation: “User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).”

    #Python #memory_graph #Equality #Hashing

     

    An exercise to help build the right mental model for Python data.

    • Solution
    • Explanation: "User-defined classes have __eq__() and __hash__() methods by default (inherited from the object class); with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)."

    #Python #memory_graph #Equality #Hashing

     

    Recursion becomes much easier once students have the right mental model. Visualization will help get them there.

    Take the Tower of Hanoi problem. The recursive solution is beautifully short, to move n disks we:

    • first remove n-1 disks from the largest disk
    • then move the largest disk
    • and then move the n-1 disks back on top

    But when students try to implement recursion, they often get stuck, and adding debug prints only adds to the confusion. That is where visualization can help to bring the right mental model. Here is the Tower of Hanoi problem solved recursively, visualized with 𝗶𝗻𝘃𝗼𝗰𝗮𝘁𝗶𝗼𝗻_𝘁𝗿𝗲𝗲: https://www.invocation-tree.com/#codeurl=https%3A%2F%2Fraw.githubusercontent.com%2Fbterwijn%2Fmemory_graph_examples%2Frefs%2Fheads%2Fmain%2Ftowers_of_hanoi.py&timestep=0.5&play=

    Instead of thinking about “a function calling itself again and again” students can now see the depth-first execution of a tree of subproblems showing the divide-and-conquer strategy in action. Once a student can think in terms of a tree of subproblems, recursion becomes much easier to understand, explain, and debug.

    #Python #invocation_tree #Recursion

     

    An exercise to help build the right mental model for Python data.

    The “Solution” link visualizes execution and reveals what’s actually happening using 𝗺𝗲𝗺𝗼𝗿𝘆_𝗴𝗿𝗮𝗽𝗵: https://github.com/bterwijn/memory_graph

     

    Data structures become much easier to understand when students can see the structure of their data visualized using memory_graph. A data structure is no longer an abstract idea but concrete, clear and debuggable. Here’s a live demo of a Linear Linked List: https://memory-graph.com/#codeurl=https%3A%2F%2Fraw.githubusercontent.com%2Fbterwijn%2Fmemory_graph%2Frefs%2Fheads%2Fmain%2Fsrc%2Flinked_list_lin.py&breakpoints=27&continues=1&timestep=0.2&play=

     

    An exercise to help build the right mental model for Python data. The “Solution” link uses memory_graph to visualize execution and reveals what’s actually happening:

    view more: next ›