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:
Choose a different operator. The obvious choice is << if his object is not already using it.
Use a method: x.set(expression)
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.
Write an interpreter that does what he likes:
code = """
x = expression """
result = interpret(code)
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.
Check out MacroPy and see whether its macros will help.
Use a custom interpreter. There is at least one superset of Python in common use: Cython.
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
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.