[Python-ideas] Operator as first class citizens -- like in scala -- or yet another new operator?
Steven D'Aprano
steve at pearwood.info
Wed May 29 09:33:47 EDT 2019
On Tue, May 28, 2019 at 05:45:54PM -0400, Ricky Teachey wrote:
> As things stand right now, it seems like you don't understand what we are
> saying about using descriptors to accomplish this. However it is certainly
> possible I simultaneously don't understand what you are really trying to do
> in the code you wrote (I definitely don't claim to).
Descriptors are, I think, a total red herring.
Yanghao Hua wants to customise the behaviour of assignment. I believe
that he wants to emulate the behaviour of some hardware description
languages, where the equals sign = doesn't mean assignment (if I have
understood correctly, which I may not have), but Something Else.
Yanghao Hua can write a method to perform that Something Else, but he
wants to use the standard variable assignment syntax:
x = expression
but there is no hook to customise the behaviour, variable assignment is
built-into the language. But *attribute assignment* is different:
obj.x = expression
may call either the descriptor protocol, or simply call type(obj).__setattr__,
which gives us the opportunity to hook into attribute assignment.
Likewise for item assignment:
obj[x] = expression
which calls type(obj).__setitem__.
So Yanghao Hua has lots of options:
1. Choose a different operator. The obvious choice is << if his object
is not already using it.
2. Use a method: x.set(expression)
3. Use a pre-processor, like Coconut or "Like, Python!". He may need to
write his own pre-processor, but that may not be very difficult if all
it does is convert "x = ..." into a method call.
4. Write an interpreter that does what he likes:
code = """
x = expression
"""
result = interpret(code)
5. It may be possible to play games with the interpreter by using
metaclasses, replacing modules with custom objects, etc. But I doubt
that will change the behaviour of assignment inside the module itself.
6. Check out MacroPy and see whether its macros will help.
7. Use a custom interpreter. There is at least one superset of
Python in common use: Cython.
8. The most obvious solution is to just use an instance and attribute:
obj.x = expression
will work fine, but he just doesn't like the look of it.
Aesthetics are an important part of language design, but it is only one
factor out of many. All languages make compromises, and sometimes
compromising on aesthetics is one of them.
In Python, the compromise is that we can't hook into plain old
assignment; but what we gain is certainty (we always know what x=...
does) and performance. On the flip side, we *can* customise attribute
assignment obj.x=... but what we lose is certainty and performance:
obj.x = ...
is slower, because it has to look up the __setattr__ method, or call the
descriptor protocol, and then call custom code; and we can't know what
it will do.
``obj.x = 1`` can call arbitrary code, so it could do literally
anything.
Extending that ability to hook assignment to plain old variables is
unlikely. It would need a PEP.
Adding a new operator like <== is less unlikely, but it too would need a
PEP, and the big question that everyone will ask is "why not just use <<
instead?"
The bottom line is, Python is not Lisp or Forth, where the very syntax
itself can be customised. Regular assignment counts as syntax: it's
unlikely to change, without a very good reason.
--
Steven
More information about the Python-ideas
mailing list