Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-08 Thread אלעזר
On Tue, Aug 9, 2016 at 12:29 AM Guido van Rossum  wrote:

> On Mon, Aug 8, 2016 at 2:11 PM, אלעזר  wrote:
>
>> Feels like named parameters are better off being an OrderedDict in the
>> first place.
>>
>
> PEP 468.
>
>
Sorry, I should have read this PEP before.


> NamedTuple pushes OrderedDict to become kind of builtin.
>>
>
> Why? Having both in the collections module is good enough.
>

What I meant in becoming builtin is not the accessibility of the name, but
the parallel incremental support of namedtuple, OrderedDict and (as I find
out) order of **kwargs.

In much the same way that class is made out of dict (and keeps one),
namedtuple is an OrderedDict (and keeps one).
Much like dict has a constructor `dict(a=1, b=2.0)` and a literal `{'a' :
1, 'b' : 2.0}`, OrderedDict has its OrderedDict(a=1, b=2.0) and should have
the literal ('a': 1, 'b': 2.0).

Replace 1 and 2 with int and float and you get a very natural syntax for a
NamedTuple that is the type of a matching OrderedDict.
And in my mind, the requirement for type names matches nicely the
enforcement of immutability.

Continuing this thought, the annotations for the class is actually its
structural type. It opens the door for future requests for adding e.g. an
operator for structural equivalence.

This is all very far from the current language, so it's only thoughts and
not really ideas; probably does not belong here. Sorry about that.

~Elazar
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-08 Thread Guido van Rossum
On Mon, Aug 8, 2016 at 3:08 PM, אלעזר  wrote:

> On Tue, Aug 9, 2016 at 12:29 AM Guido van Rossum  wrote:
>
>> On Mon, Aug 8, 2016 at 2:11 PM, אלעזר  wrote:
>>
>>> Feels like named parameters are better off being an OrderedDict in the
>>> first place.
>>>
>>
>> PEP 468.
>>
>>
> Sorry, I should have read this PEP before.
>

No problem, it's fine to participate before reading *everything*!


> NamedTuple pushes OrderedDict to become kind of builtin.
>>>
>>
>> Why? Having both in the collections module is good enough.
>>
>
> What I meant in becoming builtin is not the accessibility of the name, but
> the parallel incremental support of namedtuple, OrderedDict and (as I find
> out) order of **kwargs.
>

Well, they're all already in the stdlib, although namedtuple is written in
Python, OrderedDict in C (recently), and **kwarg is ancient.


> In much the same way that class is made out of dict (and keeps one),
> namedtuple is an OrderedDict (and keeps one).
>

I'm not sure if you're talking about the class or the instances. A class
instance usually has a dict (unless if it has __slots__ and all its base
classes have __slots__). But a namedtuple instance does not have a dict or
OrderedDict -- it is a tuple at heart.


> Much like dict has a constructor `dict(a=1, b=2.0)` and a literal `{'a' :
> 1, 'b' : 2.0}`, OrderedDict has its OrderedDict(a=1, b=2.0) and should
> have the literal ('a': 1, 'b': 2.0).
>

That's debatable at least, and probably there are better solutions.


> Replace 1 and 2 with int and float and you get a very natural syntax for a
> NamedTuple that is the type of a matching OrderedDict.
> And in my mind, the requirement for type names matches nicely the
> enforcement of immutability.
>
> Continuing this thought, the annotations for the class is actually its
> structural type. It opens the door for future requests for adding e.g. an
> operator for structural equivalence.
>
> This is all very far from the current language, so it's only thoughts and
> not really ideas; probably does not belong here. Sorry about that.
>
> ~Elazar
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-08 Thread Greg Ewing

אלעזר wrote:

class Starship(tuple):
damage: int = 0  
captain: str  = "Kirk"


Is an obvious syntax for 


Starship = NamedTuple('Starship', [('damage', int), ('captain', str)])


But the untyped version of that already has a meaning --
it's a tuple subclass with two extra class attributes
that are unrelated to its indexable items.

I thought that type annotations weren't meant to change
runtime semantics?

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-09 Thread Guido van Rossum
On Mon, Aug 8, 2016 at 11:17 PM, Greg Ewing 
wrote:

> אלעזר wrote:
>
>> class Starship(tuple):
>> damage: int = 0  captain: str  = "Kirk"
>>
>> Is an obvious syntax for
>> Starship = NamedTuple('Starship', [('damage', int), ('captain', str)])
>>
>
> But the untyped version of that already has a meaning --
> it's a tuple subclass with two extra class attributes
> that are unrelated to its indexable items.
>
> I thought that type annotations weren't meant to change
> runtime semantics?


Correct, but we can invent a new base class that has these semantics. It's
no different from Enum.

Anyway, I think this will have to be an add-on to be designed after the
basics are done.

-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-09 Thread אלעזר
It's already possible to overload NamedTuple, in a way that will allow the
following abuse of notation:

@NamedTuple
def Starship(damage:int, captain:str): pass

The 'def' is unfortunate and potentially confusing (although it *is* a
callable definition), and the ": pass" is meaningless. But I think it is
clear and concise if you know what NamedTuple is.

Introducing new keyword will of course solve both problems (if there's
"async def", why not "type def"? :) ).

 case class Starship(damage:int, captain:str)

Possible variations on the decorator theme:

"unordered" namedtuple (note the *)

@Value
def Starship(*, damage:int, captain:str): pass

self-describing (another level of notation abuse):

@Type
def Starship(damage:int, captain:str) -> NamedTuple: pass

On Mon, Aug 8, 2016 at 11:25 PM Guido van Rossum  wrote:

> That's a very interesting idea and one that deserves pursuing (though I
> agree it's not a blocker for the PEP I'm hoping to write). I think the next
> step is to prototype this -- which can only happen once we have an
> implementation of the PEP. Though perhaps you could start by writing a
> prototype that works by having the user write the following:
>
> class Starship(PrototypeNamedTuple):
> damage = 0
> captain = "Kirk"
> __annotations__ = dict(damage=int, captain=str)
>
> It could also benefit from PEP 520 (Preserving Class Attribute Definition
> Order).
>
> Who's game?
>
> --Guido
>
> On Mon, Aug 8, 2016 at 1:13 PM, אלעזר  wrote:
>
>> class Starship:
>>> stats: class Dict[str, int] = {}  # Pure class variable
>>> damage: class int = 0  # Hybrid class/instance variable
>>> captain: str  # Pure instance variable
>>>
>>
>> I can't avoid noting that there is an opportunity here to insert
>> NamedTuple into the core language. The above example is almost there,
>> except it's mutable and without convenient methods. But
>>
>> class Starship(tuple):
>> damage: int = 0
>> captain: str  = "Kirk"
>>
>> Is an obvious syntax for
>>
>> Starship = NamedTuple('Starship', [('damage', int), ('captain',
>> str)])
>>
>> Only much more available and intuitive to read, use, and of course - type
>> check.
>> (Of course, it does mean adding semantics to the declaration syntax in
>> general)
>>
>> I'm not really suggesting to make this change now, but I believe it will
>> be done, sooner or later. My brief experience with mypy convinced me that
>> it must be the case. The new declaration syntax only makes it easier.
>>
>> ~Elazar
>>
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
>
> --
> --Guido van Rossum (python.org/~guido)
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-09 Thread Eric Snow
On Tue, Aug 9, 2016 at 3:47 PM, אלעזר  wrote:
> It's already possible to overload NamedTuple, in a way that will allow the
> following abuse of notation:
>
> @NamedTuple
> def Starship(damage:int, captain:str): pass
>
> The 'def' is unfortunate and potentially confusing (although it *is* a
> callable definition), and the ": pass" is meaningless. But I think it is
> clear and concise if you know what NamedTuple is.
>
> Introducing new keyword will of course solve both problems (if there's
> "async def", why not "type def"? :) ).

If we're dealing with classes then we should be using the class
syntax.  There are a number of options here for identifying attributes
in a definition and even auto-generating parts of the class (e.g.
__init__).  Let's look at several (with various objectives):

# For the sake of demonstration, we ignore opportunities for type inference.

# currently (with comments for type info)

class Bee(namedtuple('Bee', 'name ancient_injury managerie')):
"""can a bee be said to be..."""

# name: str
# ancient_injury: bool
# menagerie: bool

def __new__(cls, name='Eric', ancient_injury=False, menagerie=False):
return super().__new__(cls, name, ancient_injury, menagerie)

def half_a(self):
return self.ancient_injury or self.menagerie


# using attribute annotations and a decorator (and PEP 520)

@as_namedtuple
class Bee:
"""..."""

name: str = 'Eric'
ancient_injury: bool = False
menagerie: bool = False

def half_a(self): ...


# using attribute annotations and a metaclass (and PEP 520)

class Bee(metaclass=NamedtupleMeta):
"""..."""

name: str = 'Eric'
ancient_injury: bool = False
menagerie: bool = False

def half_a(self): ...


# using one class decorator and PEP 520 and comments for type info

@as_namedtuple
class Bee:

name = 'Eric'  # str
ancient_injury = False  # bool
menagerie = False  # bool

def half_a(self): ...


# using one class decorator and comments for type info

@as_namedtuple('name ancient_injury managerie', name='Eric',
ancient_injury=False, menagerie=False)
class Bee:
"""..."""

# name: str
# ancient_injury: bool
# menagerie: bool

def half_a(self): ...


# using one class decorator (and PEP 468) and comments for type info
# similar to the original motivation for PEP 468

@as_namedtuple(name='Eric', ancient_injury=False, menagerie=False)
class Bee:
"""..."""

# name: str
# ancient_injury: bool
# menagerie: bool

def half_a(self): ...


# using a class decorator for each attribute

@as_namedtuple('name ancient_injury managerie')
@attr('name', str, 'Eric')
@attr('ancient_injury', bool, False)
@attr('menagerie', bool, False)
class Bee:
"""..."""

def half_a(self): ...


Those are simple examples and we could certainly come up with others,
all using the class syntax.  For me, the key is finding the sweet spot
between readability/communicating intent and packing too many roles
into the class syntax.  To be honest, the examples using attribute
annotations seem fine to me.  Even if you don't need attr type info
(which you don't most of the time, particularly with default values),
my favorite solution (a class decorator that leverages PEP 520) is
still the most readable and in-line with the class syntax, at least
for me. :)

-eric


p.s. The same approaches could also be applied to generating
non-namedtuple classes, e.g. SimpleNamespace subclasses.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-10 Thread Neil Girdhar
With PEP 520 accepted, would it be possible to iterate over 
__definition_order__?

class PrototypeNamedTuple:
cache = {}
def __new__(cls, *args):
P = PrototypeNamedTuple
if cls not in P.cache:
P.cache[cls] = typing.NamedTuple(cls.__name__, 

[(definition, cls.__annotations__[definition])
for definition in cls.__definition_order__]

)
return P.cache[cls](*args)

On Monday, August 8, 2016 at 5:09:50 PM UTC-4, Guido van Rossum wrote:
>
> Hm, overlooking the ordering is kind of a big deal for something with 
> "tuple" in its name. :-)
>
> Also it feels like it needs a metaclass instead of a cache.
>
> Maybe from this we can learn though that __anotations__ should be an 
> OrderedDict?
>
> On Mon, Aug 8, 2016 at 1:58 PM, אלעזר > 
> wrote:
>
>> class PrototypeNamedTuple:
>> cache = {}
>> def __new__(cls, *args):
>> P = PrototypeNamedTuple
>> if cls not in P.cache:
>> P.cache[cls] = typing.NamedTuple(cls.__name__, 
>> cls.__annotations__.items())
>> return P.cache[cls](*args)
>>
>> Works modulo ordering, though I'm not sure that's the right way to do it.
>>
>> The ordering part of namedtuple is orthogonal to the 
>> value-type/immutability part. So I would imagine making "Value" for the 
>> latter, "tuple" for the former, and namedtuple is mixing both (possibly 
>> given a convenient name, such as PrototypeNamedTuple). "Value" can also 
>> seen as mixing "Struct" and "Immutable", but that's overdoing it I guess.
>>
>> ~Elazar
>>
>> On Mon, Aug 8, 2016 at 11:25 PM Guido van Rossum > > wrote:
>>
>>> That's a very interesting idea and one that deserves pursuing (though I 
>>> agree it's not a blocker for the PEP I'm hoping to write). I think the next 
>>> step is to prototype this -- which can only happen once we have an 
>>> implementation of the PEP. Though perhaps you could start by writing a 
>>> prototype that works by having the user write the following:
>>>
>>> class Starship(PrototypeNamedTuple):
>>> damage = 0
>>> captain = "Kirk"
>>> __annotations__ = dict(damage=int, captain=str)
>>>
>>> It could also benefit from PEP 520 (Preserving Class Attribute 
>>> Definition Order).
>>>
>>> Who's game?
>>>
>>> --Guido
>>>
>>> On Mon, Aug 8, 2016 at 1:13 PM, אלעזר > 
>>> wrote:
>>>
 class Starship:
> stats: class Dict[str, int] = {}  # Pure class variable
> damage: class int = 0  # Hybrid class/instance variable
> captain: str  # Pure instance variable
>

 I can't avoid noting that there is an opportunity here to insert 
 NamedTuple into the core language. The above example is almost there, 
 except it's mutable and without convenient methods. But

 class Starship(tuple):
 damage: int = 0  
 captain: str  = "Kirk"

 Is an obvious syntax for 

 Starship = NamedTuple('Starship', [('damage', int), ('captain', 
 str)])

 Only much more available and intuitive to read, use, and of course - 
 type check.
 (Of course, it does mean adding semantics to the declaration syntax in 
 general)

 I'm not really suggesting to make this change now, but I believe it 
 will be done, sooner or later. My brief experience with mypy convinced me 
 that it must be the case. The new declaration syntax only makes it easier.

 ~Elazar

 ___
 Python-ideas mailing list
 python...@python.org 
 https://mail.python.org/mailman/listinfo/python-ideas
 Code of Conduct: http://python.org/psf/codeofconduct/

>>>
>>>
>>>
>>> -- 
>>> --Guido van Rossum (python.org/~guido)
>>>
>>
>
>
> -- 
> --Guido van Rossum (python.org/~guido)
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-10 Thread Guido van Rossum
Sounds like you're thinking with your runtime hat on, not your type checker
hat. :-)

On Tue, Aug 9, 2016 at 9:46 PM, Neil Girdhar  wrote:

> With PEP 520 accepted, would it be possible to iterate over
> __definition_order__?
>
> class PrototypeNamedTuple:
> cache = {}
> def __new__(cls, *args):
> P = PrototypeNamedTuple
> if cls not in P.cache:
> P.cache[cls] = typing.NamedTuple(cls.__name__,
>
> [(definition, cls.__annotations__[definition])
> for definition in cls.__definition_order__]
>
> )
> return P.cache[cls](*args)
>
> On Monday, August 8, 2016 at 5:09:50 PM UTC-4, Guido van Rossum wrote:
>>
>> Hm, overlooking the ordering is kind of a big deal for something with
>> "tuple" in its name. :-)
>>
>> Also it feels like it needs a metaclass instead of a cache.
>>
>> Maybe from this we can learn though that __anotations__ should be an
>> OrderedDict?
>>
>> On Mon, Aug 8, 2016 at 1:58 PM, אלעזר  wrote:
>>
>>> class PrototypeNamedTuple:
>>> cache = {}
>>> def __new__(cls, *args):
>>> P = PrototypeNamedTuple
>>> if cls not in P.cache:
>>> P.cache[cls] = typing.NamedTuple(cls.__name__,
>>> cls.__annotations__.items())
>>> return P.cache[cls](*args)
>>>
>>> Works modulo ordering, though I'm not sure that's the right way to do it.
>>>
>>> The ordering part of namedtuple is orthogonal to the
>>> value-type/immutability part. So I would imagine making "Value" for the
>>> latter, "tuple" for the former, and namedtuple is mixing both (possibly
>>> given a convenient name, such as PrototypeNamedTuple). "Value" can also
>>> seen as mixing "Struct" and "Immutable", but that's overdoing it I guess.
>>>
>>> ~Elazar
>>>
>>> On Mon, Aug 8, 2016 at 11:25 PM Guido van Rossum 
>>> wrote:
>>>
 That's a very interesting idea and one that deserves pursuing (though I
 agree it's not a blocker for the PEP I'm hoping to write). I think the next
 step is to prototype this -- which can only happen once we have an
 implementation of the PEP. Though perhaps you could start by writing a
 prototype that works by having the user write the following:

 class Starship(PrototypeNamedTuple):
 damage = 0
 captain = "Kirk"
 __annotations__ = dict(damage=int, captain=str)

 It could also benefit from PEP 520 (Preserving Class Attribute
 Definition Order).

 Who's game?

 --Guido

 On Mon, Aug 8, 2016 at 1:13 PM, אלעזר  wrote:

> class Starship:
>> stats: class Dict[str, int] = {}  # Pure class variable
>> damage: class int = 0  # Hybrid class/instance variable
>> captain: str  # Pure instance variable
>>
>
> I can't avoid noting that there is an opportunity here to insert
> NamedTuple into the core language. The above example is almost there,
> except it's mutable and without convenient methods. But
>
> class Starship(tuple):
> damage: int = 0
> captain: str  = "Kirk"
>
> Is an obvious syntax for
>
> Starship = NamedTuple('Starship', [('damage', int), ('captain',
> str)])
>
> Only much more available and intuitive to read, use, and of course -
> type check.
> (Of course, it does mean adding semantics to the declaration syntax in
> general)
>
> I'm not really suggesting to make this change now, but I believe it
> will be done, sooner or later. My brief experience with mypy convinced me
> that it must be the case. The new declaration syntax only makes it easier.
>
> ~Elazar
>
> ___
> Python-ideas mailing list
> python...@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>



 --
 --Guido van Rossum (python.org/~guido)

>>>
>>
>>
>> --
>> --Guido van Rossum (python.org/~guido)
>>
>


-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-10 Thread Eric Snow
On Wed, Aug 10, 2016 at 11:56 AM, Guido van Rossum  wrote:
> Sounds like you're thinking with your runtime hat on, not your type checker
> hat. :-)
>
> On Tue, Aug 9, 2016 at 9:46 PM, Neil Girdhar  wrote:
>>
>> With PEP 520 accepted, would it be possible to iterate over
>> __definition_order__?

Still, it would be really nice to be able to introspect a class's
instance attributes at run-time.  A stdlib helper for that would be
great, e.g. "inspect.get_inst_attrs(cls)".  At one point a few years
back I wrote something like that derived from the signature of
cls.__init__() and in the spirit of inspect.signature().  It turned
out to be quite useful.

Relatedly, it may make sense to recommend in PEP 8 that all instance
attribute declarations in a class definition be grouped together and
to do so right before the methods (right before __new__/__init__?).
(...or disallow instance attribute declarations in the stdlib for
now.)

-eric
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-10 Thread Guido van Rossum
On Wed, Aug 10, 2016 at 4:04 PM, Eric Snow 
wrote:
[...]
>
> Still, it would be really nice to be able to introspect a class's
> instance attributes at run-time.  A stdlib helper for that would be
> great, e.g. "inspect.get_inst_attrs(cls)".  At one point a few years
> back I wrote something like that derived from the signature of
> cls.__init__() and in the spirit of inspect.signature().  It turned
> out to be quite useful.
>

Yes, the proposal will store variable annotations for globals and for
classes in __annotations__ (one global, one per class). Just not for local
variables.


> Relatedly, it may make sense to recommend in PEP 8 that all instance
> attribute declarations in a class definition be grouped together and
> to do so right before the methods (right before __new__/__init__?).
> (...or disallow instance attribute declarations in the stdlib for
> now.)
>

Let's wait until we have some experience with how it's used before updating
PEP 8... :-)

-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Trial balloon: adding variable type declarations in support of PEP 484

2016-08-11 Thread Eric Snow
On Tue, Aug 9, 2016 at 5:32 PM, Eric Snow  wrote:
> There are a number of options here for identifying attributes
> in a definition and even auto-generating parts of the class (e.g.
> __init__).  Let's look at several (with various objectives):
>
> # currently (with comments for type info)
> # using attribute annotations and a decorator (and PEP 520)
> # using attribute annotations and a metaclass (and PEP 520)
> # using one class decorator and PEP 520 and comments for type info
> # using one class decorator and comments for type info
> # using one class decorator (and PEP 468) and comments for type info
> # using a class decorator for each attribute

Another approach that I've used in the past (along with a derivative):

# using a non-data descriptor

@as_namedtuple
class Bee:
"""..."""

name = Attr(str, 'Eric', doc='the bee's name')
ancient_injury = Attr(bool, False)
menagerie = Attr(bool, False)

def half_a(self): ...


# using a non-data descriptor along with PEP 487

class Bee(Namedtuple):
"""..."""

name = Attr(str, 'Eric', doc='the bee's name')
ancient_injury = Attr(bool, False)
menagerie = Attr(bool, False)

def half_a(self): ...

While the descriptor gives you docstrings (a la property), I expect it
isn't as static-analysis-friendly as the proposed variable
annotations.

-eric
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/