[–] [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
  • [–] [S] 2 points 1 month ago* (2 children)

    Can you tell me what the problem is for you when you click the first link? I tried to make it work for all browsers (even mobile, but the UI isn't very mobile friendly), so I would like to get it working on your system too. If you can give me a bug report (and maybe try from different system), that would be great.

    The second link explains:

    It's left to the reader to generalize this to x |= y vs x = x | y.

  • source
  • parent
  • context
  • [–] [S] 1 point 1 month ago* (last edited 1 month ago)

    The dict union operator is similar to that of set, but in addition the right operand overwrites values of keys of the left operand. It's a nice operator once you get used to it.

    Easy to make a mistake with this exercise:

    • first realize b = b | {3: []} makes a shallow copy
    • then realize the shallow copy still references the value of key 2 in a so we can still append to that and change a
  • source
  • parent
  • context
  • [–] [S] 1 point 2 months ago* (last edited 2 months ago)

    Yes indeed, the 'int' objects are stored and searched in the set based on their value, and the 'Value' objects are stored/searched based on their identity unless you define the above __eq__ and __hash__ methods which cause them to be stored/searched based on value too. This is a Python design decision and that's the point of this exercise. The fact that 'int' is an immutable type and we are replacing isn't relevant. Try replacing/reassigning the 'Value' objects after added __eq__ and __hash__, and you get the same result as for 'int'. So the thing that really matters is how __eq__ and __hash__ are defined, and the default for a user-defined class is as stated in the "Explanation:" above.

    Maybe I should also show a class with __eq__ and __hash__ defined based on value, but then it gets a bit long. I'll have to rethink this exercises so that the point comes across better as it now seems to confuse a lot of people based on the down-votes. Thanks for feedback anyway.

  • source
  • parent
  • context
  • [–] [S] 2 points 2 months ago* (last edited 2 months ago) (2 children)

    Sure, but a lot of people incorrectly think the __eq__ and __hash__ are defined based on value not identity, as they are for many other types say float, str, or tuple. But for a class the default __eq__ method is x is y instead of x == y and also __hash__ is based on identity.

    Others assume that if you don't define __hash__ for a class, that it doesn't exists (like for list, set, or dict) so that a "TypeError: unhashable type: 'Value'" exception is raised.

    I thought it was an interesting exercise to share, but maybe too simple for this audience, or people are just not aware of the basic steps that happen when adding and searching values in a set/dict. Try the same with type int:

    v1 = 1001
    v2 = 1002
    myset = {v1}
    print(v1 in myset, end=' ')
    v2 = 1001
    print(v2 in myset, end=' ')
    v1 = 1002
    print(v1 in myset, end=' ')
    

    and you see a different output. To do the same with the Value class add methods:

    def __eq__(self, other):
        return self.value == other.value
    
    def __hash__(self):
        return hash(self.value)
    
  • source
  • parent
  • context
  • view more: next ›