On Thu, Oct 1, 2020 at 2:14 AM Jason C. McDonald <codemous...@outlook.com> wrote: > > > > I have a great idea, there are __iX__` methods, such as `__ior__`, > > `__iadd__`, `__iand__` etc.., which implements the |=, +=, &= > > behavior, > > it would be nice if you could implement also `__igetattr__` or > > something, which means: > > > > instead of > > con = "some text here" > > con = con.replace("here", "there") > > > > we could do > > > > con = "some text here" > > con .= replace("here", "there") > > I have three concerns about this. First, there's a lot of wizardry > under the covers with getattr() and dot access to begin with, so this > would be significantly non-trivial. I suspect the behavior would wind > up being "surprising" too often. > > Second, explicit is better than implicit. It's better to explicitly > rebind the name (or mutate on the name) rather than have a fancy > shorthand for trampling over an existing mutable value. In the case of > the compound operators on numbers, you're dealing with immutable types > anyway, so you're really just rebinding the name. The same is true of > your string there. But what about a list? > > spam = [1, 2, 3] > eggs = spam > eggs .= append(4) # what is happening???? > eggs .= sort() # how about now? > eggs .= sorted(eggs) # and now? > > You see? It's going to be a lot of surprises, because you're stripping > the usual visual cues of explicit assignment: > > spam = [1, 2, 3] > eggs = spam > eggs.append(4) # mutating spam too > eggs.sort() # mutating spam too > eggs = eggs.sorted() # rebinding eggs to a new value, spam is safe >
These examples reveal a few other issues, though, which can best be highlighted by this: x = 5 x *= 2 + 3 print(x) x = 5 x = x * 2 + 3 print(x) Augmented assignment works with a single other operand. It's not textually equivalent to "x = x <op> other"; it's closer to "x = x <op> (other)", putting the right hand side in parentheses. That doesn't work with a hypothetical igetattr, because you're invariably going to want to do more than just get an attribute. It's also notable that the in-place *methods* are actually used something like this (omitting detaily bits about slots): x += y # is roughly equivalent to x = x.__iadd__(y) So there's assignment *as well as* the in-place method call. The only value of the __iadd__ family of methods is with types that can implement them directly; for instance, a list can append to itself, rather than copying itself and then reassigning (which is semantically different, as well as being far less efficient). The ".=" operator wouldn't be able to take advantage of that. If you find yourself frequently writing long chains of statements that all do "thing = thing.method()", it may be better to consider writing them as a single statement instead: name = (name .capitalize() .expandtabs() .lstrip(" ") .replace(", ", ",") ) It'd be as efficient and readable as the augmented assignment form would be. ChrisA -- https://mail.python.org/mailman/listinfo/python-list