[Python-ideas] Quick idea: defining variables from functions that take the variable name

Piotr Duda duda.piotr at gmail.com
Tue May 31 02:35:25 EDT 2016


3 years ago, I've proposed syntax

def name = expr

for binding names to arbitrary objects

https://mail.python.org/pipermail/python-ideas/2013-May/020501.html


2016-05-31 6:57 GMT+02:00 Joshua Morton <joshua.morton13 at gmail.com>:

> I like the arrow idea, another option is a syntax more in line with the
> one being discussed for dict unpacking, something like adding a __define__
> dunder that returns a tuple of (name, value). So that say, Typevar's
> __define__ returns the tuple `(self.__name__, self)`. Which is then
> converted into an assignment. The downside of this being that its
> assignment overloading(which can be abused), but at least it can only be
> done when specifically asked for. The other downside is that the syntax
>
> define TypeVar('T')  # and I assume we can also declare a list of them
> def ident(t: T) -> T:
>     return t
>
> looks both foreign and a bit magical. Also new keyword, but I have a
> feeling that the same keyword could probably be used here and with dict
> unpacking. (the *really* big downside is for a library implementer to do
> something devious like have __define__ always return ("constant", self), or
> generally something that wasn't clear to the caller, because we get names
> appearing out of no where with no clear history, but my argument would be
> that we should trust libraries not to do that and say that it is a very bad
> thing)
>
> The upside is that it avoids the problem of Steven's implementation, since
> the name is decided internally by the callable.
>
> Like with his example, define `Typevar('7')` and similar invalid names
> would throw an error, in this case probably a TypeError.
>
> --Josh
>
>
> On Mon, May 30, 2016 at 11:08 PM Steven D'Aprano <steve at pearwood.info>
> wrote:
>
>> On Mon, May 30, 2016 at 06:16:26PM -0700, Guido van Rossum wrote:
>>
>> [...]
>> >   T = TypeVar('T')
>> >   x = Symbol('x')
>> >
>> > I'm sure this is not a new idea, but so far I've always thought that
>> > this is pretty esoteric and the approach here is good enough. But
>> > maybe we can actually do better, and whatever solution we come up with
>> > might also be useful for extracting attributes from an object or
>> > values from a mapping?
>>
>> This comes up a lot and it would be nice to clean it up.
>>
>> T = type('T', bases, ns)
>> Record = namedtuple('Record', fields)
>>
>> It came up in the discussion on dict unpacking:
>>
>> a, b, c = **dict  # unpacks keys 'a', 'b', 'c'
>>
>> which was rejected as too magical. But maybe it will seem less magical
>> if we have a special assignment operator that takes the left hand
>> symbol(s)
>> and copies them to the right?
>>
>> How do you feel about an arrow operator?
>>
>>
>> T -> TypeVar()
>> x -> Symbol()
>> T -> type(bases, ns)
>> Record -> namedtuple(fields)
>>
>> In general:
>>
>> name [, name, ...] -> callable(...)
>>
>> where "callable" is some expression, e.g. a name, a dot lookup, etc.
>>
>> # okay
>> name -> sympy.Symbol()
>>
>>
>>
>> The easy case
>> -------------
>>
>> All assignment targets are plain names.
>>
>> The arrow operator takes the names, turns them into strings, and passes
>> them to the callable on the right as a tuple of strings, given as the
>> first
>> positional argument.
>>
>> Since the most common case will be a single target, I think it is worth
>> while to treat it as a special case and pass just a string:
>>
>> T -> Type()  # like Type('T')
>>
>> a, b, c -> Spam(arg)  # like Spam(('a', 'b', 'c'), arg)
>>
>> The callable being called doesn't need to know or care whether it is
>> being called with the -> or = assignment. It just receives the name(s)
>> as the first argument.
>>
>> This will mean that callables that take the name as (say) the second
>> argument cannot be used with this syntax.
>>
>> Using the arrow operator with arbitrary expressions on the
>> right will be a SyntaxError:
>>
>> x -> y + 1
>> my_name -> spam*f()
>> my_name -> f() or g()
>>
>> I reject that third example as it is unclear whether both f and g, or
>> only f, get the name as first argument.
>>
>> But this is allowed:
>>
>> my_name -> f(g())  # like f('my_name', g())
>>
>> If f isn't *actually* a callable, you get a runtime TypeError as usual.
>>
>>
>> The hard case
>> -------------
>>
>> Assignment target(s) is not a plain name.
>>
>> spam[2].eggs().attr -> Symbol()
>>
>>
>> I'm going to take the cowards way out and just say "we don't allow
>> that".
>>
>>
>> --
>> Steve
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



-- 
闇に隠れた黒い力
弱い心を操る
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160531/62fbb872/attachment.html>


More information about the Python-ideas mailing list