While I am not at this point dropping the idea of @decorator(expression) targetname a thought occurred to me yesterday after discussing targetname as a string in assignments (and I appreciate the continued discussion in a new thread but this is a new counter proposal so keeping it here). There is at least one other place where python saves us from retyping the lhs in an assignment statement: augmented assignment. It is not being used as a string, true, and it's much more difficult to introduce a subtle bug by mis-typing the name if one were to use the standard operator instead. But we still have augmented assignment for all operators IMO because programmers are productively lazy and came up with a way to not retype their variable.
What if, instead of adding a new magic symbol to the assignment statement (statements? still not sure which ones are supported in the counter proposal) we add a new assignment operator and corresponding dunder method that would perform the real operation behind the syntactic sugar.
For now I propose the operator "<==" and dunder "__assign__". Both very bikeshedable, but allows us to draw some examples
RED <== str
RED = str.__assign__("RED") # or is this how it's actually done? don't remember # RED = type(str).__assign__(str, "RED")
where str now has the method
def __assign__(cls, assignment_name): return assignment_name
Following the example of augmented assignment, both of these would be SyntaxErrors:
spam = eggs <== str spam, eggs <== str
Although there is probably a way to make the second one work, that can be experimented with in a reference implementation or saved for a later PEP.
Some more of my original examples with the new operator:
Point <== namedtuple("x y z")
UUIDType: str <== NewType
Colors <== Enum("RED GREEN BLUE")
class Colors(Enum): RED <== str GREEN <== str BLUE< == str
It would also be possible to reuse a factory, similar to the way a decorator that takes arguments first creates a sort of closure and is then that is passed the function object in a subsequent call.
SPAM_DB <== get_sql_db(pass=_secret, user=user) TABLE1 <== SPAM_DB TABLE2 <== SPAM_DB
would be the same as
SPAM_DB = get_sql_db(pass=_secret, user=user).__assign__("SPAM_DB") TABLE1 = SPAM_DB.__assign__("TABLE1") TABLE2 = SPAM_DB.__assign__("TABLE2")