Hello, Today I found myself write a function that returns a tuple of list of list of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it easier to read to write it like the following: ([[str]], [[str]])? Similarly for TypedDict, replace the following.. class Movie(TypedDict): name: str year: int with {‘name’: str, ‘year’: int} dict[str, int] will be {str: int} set[int] will be {int}. This is similar to the new proposed Callable alternative (i.e., (int, float) -> float) since it mimics the structure of a function. Also, Annotated[float, “seconds”] can be replaced with something like float #seconds indicating whatever comes after the hashtag is just extra information similar to a normal comment in the code. Imagine you could replace the following def func(d: dict[Annotated[str, “product label”], Annotated[list[float], “prices from 2000 to 2015”]])… With def func(d: {str # product label: [float] # prices from 2000 to 2015})… Abdulla Sent from my iPhone
I find myself using exactly that "picture of the data" approach informally for code I don't plan on formally type checking (but want to show intent). E.g. def myfun(data: {str: [CustomType]}) -> [(int, OtherType)]: ... Maybe it's a bad habit, but it feels easier to parse visually than the real `typing.py` stuff. On Wed, Oct 13, 2021, 4:35 PM Abdulla Al Kathiri < alkathiri.abdulla@gmail.com> wrote:
Hello,
Today I found myself write a function that returns a tuple of list of list of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it easier to read to write it like the following: ([[str]], [[str]])? Similarly for TypedDict, replace the following..
class Movie(TypedDict): name: str year: int
with {‘name’: str, ‘year’: int} dict[str, int] will be {str: int} set[int] will be {int}. This is similar to the new proposed Callable alternative (i.e., (int, float) -> float) since it mimics the structure of a function.
Also, Annotated[float, “seconds”] can be replaced with something like float #seconds indicating whatever comes after the hashtag is just extra information similar to a normal comment in the code. Imagine you could replace the following def func(d: dict[Annotated[str, “product label”], Annotated[list[float], “prices from 2000 to 2015”]])… With def func(d: {str # product label: [float] # prices from 2000 to 2015})… Abdulla Sent from my iPhone _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/D6LHXD... Code of Conduct: http://python.org/psf/codeofconduct/
On Thu, Oct 14, 2021 at 12:32:57AM +0400, Abdulla Al Kathiri wrote:
Today I found myself write a function that returns a tuple of list of list of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it easier to read to write it like the following: ([[str]], [[str]])?
Not really. Your first example is explicit and I can get the meaning by just reading it out loud: tuple[list[list[str]], list[list[str]]] "tuple (of) list (of) list (of) str, list (of) list (of) str Your abbreviated version: ([[str]], [[str]]) is too terse. I have to stop and think about what it means, not just read it out loud. Without the hint of named types (tuple and list), my first reaction to seeing [str] is "is this an optional string?". And then I wonder why it's not written: ([[""]], [[""]]) Why abbreviate list and tuple but not string? Code is read more than it is written, and can be too terse as well as too verbose. On the other hand:
Similarly for TypedDict, replace the following.. class Movie(TypedDict): name: str year: int with {‘name’: str, ‘year’: int}
To my eye, that one does work. As far as I know, curly brackets {} aren't otherwise used in annotations (unlike square brackets), and they don't look like "optional" to me. They look like a dict. So on first glance at least, I think that: {'name': str, 'year': int} is better than the class syntax we already have. Likewise:
dict[str, int] will be {str: int} set[int] will be {int}.
work for me too.
Also, Annotated[float, “seconds”] can be replaced with something like float #seconds indicating whatever comes after the hashtag is just extra information similar to a normal comment in the code.
No, because the # indicates that the rest of the line is a comment. This is already legal: def func(d: {str # this is an actual comment : int}) -> Any: ... so this would be ambiguous between a real comment and an annotation. Even if we agreed to change the behaviour of comments, you suggested: func(d: {str # product label: [float] # prices from 2000 to 2015}) How is the interpreter to know that the first annotation is just "product label" rather than this? "product label: [float] # prices from 2000 to 2015" So I don't think this works. -- Steve
On 14 Oct 2021, at 12:21 PM, Steven D'Aprano <steve@pearwood.info> wrote:
Why abbreviate list and tuple but not string?
Empty strings would be confusing as a type unless you mean a Literal empty string. We just limit the picture of the type to lists, tuples, dicts, and sets. Builtin most often used collections. Imagine you have a default parameter like this... name: “” = “”. This adds unnecessary confusion.
Not really. Your first example is explicit and I can get the meaning by just reading it out loud:
tuple[list[list[str]], list[list[str]]]
"tuple (of) list (of) list (of) str, list (of) list (of) str
Your abbreviated version:
([[str]], [[str]])
is too terse. I have to stop and think about what it means, not just read it out loud. Without the hint of named types (tuple and list), my first reaction to seeing [str] is "is this an optional string?".
I am a visual guy. ([[str]], [[str]]) is much easier to my eyes than reading tuple (of) list (of) list (of) str, list (of) list (of) str.
don't look like "optional" to me
Optional would be Optional[str] or str | None, not [str].
No, because the # indicates that the rest of the line is a comment. This is already legal:
def func(d: {str # this is an actual comment : int}) -> Any: ...
so this would be ambiguous between a real comment and an annotation.
Even if we agreed to change the behaviour of comments, you suggested:
func(d: {str # product label: [float] # prices from 2000 to 2015})
How is the interpreter to know that the first annotation is just
"product label"
rather than this?
"product label: [float] # prices from 2000 to 2015"
So I don't think this works.
# is not a good idea I agree. How about the following for Annotated: func(d: {str & "product label": [float] & "prices from 2000 to 2015"})? The “&” is similar to “& co.” (and company). They come together but the first one is the group leader and represents all of them. It works in an opposite way to “|” (or), which gives importance equally to the members. def func( time: float & “hours” & datetime.timedelta.total_seconds()/3600, verbose: bool & “option for long text” = False, ) -> str: … Abdulla
participants (3)
-
Abdulla Al Kathiri
-
David Mertz, Ph.D.
-
Steven D'Aprano