[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