[Python-Dev] Re: RFC on Callable Syntax PEP
To me, these are mostly convincing examples that people need to name parts of a complex type like this :-) I don't actually find any of the syntaxes better than any other. They are all a bit bad, but I view that as the fault of the complex nested types, not the syntax (hence my preference for naming things). It's hard to give examples of how I'd name things, because you need to know the "business logic" to name things well, and I don't for these. Frankly, if people were writing normal Python expressions like this, everyone would be telling them that Python isn't about writing one-liners and they should factor out named subexpressions. Why should type annotations be any different? Paul PS If I wanted any improvement for callables, it would be to use parentheses for the arguments rather than square brackets (which look too "heavy" in my view). So Callable[(int, str), bool] rather than Callable[[int, str], bool]. I understand why the outer brackets have to be square (abuse of indexing notation) but as far as I can see there's no reason the inner ones need to be (OK, for single arguments, Callable[(int,), bool] is a bit clumsy...) On Tue, 21 Dec 2021 at 22:10, Steven Troxler wrote: > > In the example I was aiming for something easy to understand that produced a > type illustrating potential problems of PEP 677, which is at its worst when > there are callables in both argument and return position. I don't have a > great real-world example of this worst-case, most of what I've seen involves > simpler and the current PEP 677 proposal isn't as bad. > > As for formatting I agree that I wouldn't hand-write the type as > ``` > ((int) -> float, (str) -> bool) -> (int, str) -> tuple[float, bool] > ``` > but a lot of code formatters might fight me on this, so I think it's worthy > of consideration, and I was trying to illustrate a readability problem and > possible fix. Formatting the code nicely so that my proposal looks good would > have meant not really engaging with the concern. > > If you're looking for examples from real code where Callable is unweildy, > Pradeep collected a few at [1] from typeshed although most of them look just > fine with the current PEP 677 proposal. A couple examples: > > Callable[[AnyStr, Callable[[AnyStr, AnyStr, AnyStr], AnyStr]], AnyStr] > Callable[[Optional[str], tuple[_Marshallable, ...]], Union[Fault, > tuple[_Marshallable, ...]]] > Callable[[str, Callable[[Iterable[str], str], str]], None] > > versus the same types written using the current PEP 677 syntax: > > (AnyStr, (AnyStr, AnyStr, AnyStr) -> AnyStr) -> AnyStr > (Optional[str], tuple[_Marshallable, ...]) -> Union[Fault, > tuple[_Marshallable, ...]] > (str, (Iterable[str], str) -> str) -> None > > versus with outer parentheses: > > (AnyStr, (AnyStr, AnyStr, AnyStr -> AnyStr) -> AnyStr) > (Optional[str], tuple[_Marshallable, ...] -> Union[Fault, > tuple[_Marshallable, ...]]) > (str, (Iterable[str], str -> str) -> None) > > and another idea, requiring both outer parentheses and argument parentheses: > > ((AnyStr, ((AnyStr, AnyStr, AnyStr )-> AnyStr)) -> AnyStr) > ((Optional[str], tuple[_Marshallable, ...]) -> Union[Fault, > tuple[_Marshallable, ...]]) > (str, (Iterable[str], str) -> str) -> None) > > To me, these are convincing examples of where Callable is hard to read and an > arrow syntax is easier, but that doesn't necessarily mean it's worth the > price of new syntax. > ___ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/KWQVEQDZFBZDQDLOGATXSFN7KSF4WVYJ/ > Code of Conduct: http://python.org/psf/codeofconduct/ ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/CMDXHQPLJMGCJLL2SVPFJLC3CRE5AUYU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: RFC on Callable Syntax PEP
In the example I was aiming for something easy to understand that produced a type illustrating potential problems of PEP 677, which is at its worst when there are callables in both argument and return position. I don't have a great real-world example of this worst-case, most of what I've seen involves simpler and the current PEP 677 proposal isn't as bad. As for formatting I agree that I wouldn't hand-write the type as ``` ((int) -> float, (str) -> bool) -> (int, str) -> tuple[float, bool] ``` but a lot of code formatters might fight me on this, so I think it's worthy of consideration, and I was trying to illustrate a readability problem and possible fix. Formatting the code nicely so that my proposal looks good would have meant not really engaging with the concern. If you're looking for examples from real code where Callable is unweildy, Pradeep collected a few at [1] from typeshed although most of them look just fine with the current PEP 677 proposal. A couple examples: Callable[[AnyStr, Callable[[AnyStr, AnyStr, AnyStr], AnyStr]], AnyStr] Callable[[Optional[str], tuple[_Marshallable, ...]], Union[Fault, tuple[_Marshallable, ...]]] Callable[[str, Callable[[Iterable[str], str], str]], None] versus the same types written using the current PEP 677 syntax: (AnyStr, (AnyStr, AnyStr, AnyStr) -> AnyStr) -> AnyStr (Optional[str], tuple[_Marshallable, ...]) -> Union[Fault, tuple[_Marshallable, ...]] (str, (Iterable[str], str) -> str) -> None versus with outer parentheses: (AnyStr, (AnyStr, AnyStr, AnyStr -> AnyStr) -> AnyStr) (Optional[str], tuple[_Marshallable, ...] -> Union[Fault, tuple[_Marshallable, ...]]) (str, (Iterable[str], str -> str) -> None) and another idea, requiring both outer parentheses and argument parentheses: ((AnyStr, ((AnyStr, AnyStr, AnyStr )-> AnyStr)) -> AnyStr) ((Optional[str], tuple[_Marshallable, ...]) -> Union[Fault, tuple[_Marshallable, ...]]) (str, (Iterable[str], str) -> str) -> None) To me, these are convincing examples of where Callable is hard to read and an arrow syntax is easier, but that doesn't necessarily mean it's worth the price of new syntax. ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/KWQVEQDZFBZDQDLOGATXSFN7KSF4WVYJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: facing the issue for remove the value from list (when value is repeated)
Hello! The python-dev list is for developing the next version of Python. For help using Python, please send your question to python-l...@python.org Thanks, and good luck! -- ~Ethan~ ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/UED6OIEVBCF2MW4CPIO7EXYS3OTNTQME/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] facing the issue for remove the value from list (when value is repeated)
Good evening everyone I used python 3.7.3 IDLE i found the bug to solve the problem when list contain repetitive value is come i.e. if i want to delete 2 from list using remove function it's 2 value put containouls 2 and such value is remove using any type of loop all element are not delete from list. Any higher version cover such type of problem? or any other method for delete such value list1=[1,2,3,2,4,2,7,2,2,2,2,5,5,5,2,4,5,6,7,8] a=0 while a < len(list1): if list1[a]==2: list1.remove(2) a=a+1 print(list1) ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/QJHHX2YAP2TQHS7O545B5GUVPVBJC6ZI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: RFC on Callable Syntax PEP
Ahah, that makes sense. But then I think I buy into your reasoning that this isn't really a replacement for callable syntax (although functions as types opens up other interesting possibilities). For this and other reasons I'd hate to see callable syntax rejected in favor of it, so definite +1 on new callable syntax for me. p.s. I'm +0.5 on | binding tighter than -> ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ZURCWPSOE72MFPWONUIOH3XWVJ6ETWR5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: RFC on Callable Syntax PEP
I agree with what Batuhan said. Adding on, I'm very concerned about the potential maintenance burden for Python implementations. Just for typing in CPython, some combination of the following knowledge is required to contribute code: 1. Metaclasses 2. Descriptors and CPython dunders 3. C internals due to PEP 585 and 604 4. If we throw in annotations internals, maybe we need some parser knowledge too, but this is usually not required. With the new callable syntax, that likely needs strong parser and compiler knowledge. I'm not claiming everyone needs to know all of the above to contribute (to the contrary, not knowing most of these is fine), but IMO the list is getting very long. I'd be sad if one day new typing contributors feel too overwhelmed by typing's implementation complexity (I admit sometimes feeling overwhelmed too). That said, thank you PEP authors for working to make Python's typing syntax more elegant. I hope my concerns didn't come across as overly harsh. - KJ ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/YZG53T2D3UO6WZCR5U3N45GVAK3E7JPN/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: RFC on Callable Syntax PEP
On Tue, 21 Dec 2021 at 18:35, Steven Troxler wrote: > > I've been thinking about readability hard because I share many of your > concerns about readability. Before I comment on syntax, I'd like to question the example: > An example > = > > The function > > > To get at what I mean, here's a nice simple function: > ``` > def zip(f, g): > def zipped(x: int, y: str): > return f(x), g(y) > return zipped > ``` So my first question is why a generic function like this would limit the parameters x and y to int and str. Surely this is an entirely workable function for *any* arguments with the appropriate "shape"? So how is this a good example of somewhere you'd use types like Callable[[int], bool] (by the way, where did that "bool" appear from?) in a signature? My immediate thought when seeing that zip function is that its type is "obvious"¹, (takes two functions, returns a function which takes 2 arguments matching the args of the 2 functions and returns a tuple matching the results of the 2 functions). That type is almost impossible to express clearly, because it needs pretty complex generics. But the more important point is that I'd never, **ever**, want to write that type out longhand. I'd expect a type system to either infer the type, and it would be anonymous¹, or to give up and treat it as untyped. One thing I absolutely would not want to do is over-constrain any of the arguments just to make it possible to write the type down. The real issue with this function, in my view, is not expressing callables, but rather generic type variables ("return a function whose first argument has the same type as the single argument of the function which is the first argument of this function..." !!!) Can you suggest a more "real world" function as an example, which focuses on the callable syntax and doesn't use things like arguments called f and g? Maybe a GUI callback with a function argument like on_click? ¹ By which I mean intuitive, not easy to express in words!!! :-) ² Some languages may allow syntax like `typeof(zip)` to refer to that anonymous type, but that's a separate point. > Here's it's type using typing.Callable: > ``` > typing.Callable[ > [typing.Callable[[int], bool], typing.Callable[[str], float]], > typing.Callable[[int, str], tuple[bool, float] > ] > ``` > which seems ugly. It's actually not bad compared to a lot of production code, > but this is the kind of thing that led to PEP 677. It's massively over-constrained. I assume that's because you're trying to make a point about Callable[] rather than about generics, but can you give a realistic example that *doesn't* involve over-constraining higher order functions? On a side note, why not name at least some of those function types? And why not use "from typing import Callable"? It feels like you're not making enough effort to make your example readable, which undermines your point as a result. > ((int) -> float, (str) -> bool) -> (int, str) -> tuple[float, bool] To your credit, you've made this pretty unreadable, which gives some balance here :-) Seriously, making it a one-liner with all those -> arrows is a disaster. Changing the location of the parentheses doesn't alter that at all. Rewriting as a multi-line expression: ( (int) -> float, (str) -> bool ) -> (int, str) -> tuple[float, bool] helps quite a bit, but returning a function looks bad here. We're not writing Haskell, you know ;-) I'd prefer a "mixed" notation here: ( (int) -> float, (str) -> bool ) -> Callable[(int, str), tuple[float, bool]] I don't honestly think there's a readable "function returning a function" form here - the chained -> tokens is just awkward. Although that's clearly a matter of preference, there's never going to be an objective answer here. > Here’s the type if we change the syntax to put the right parenthesis after > the return type: > ``` > ((int -> float), (str -> bool) -> (int, str -> tuple[float, bool]) > ``` > > To my eyes, most of the pain points are now eliminated. > - there’s never a double-arrow due to callable in return position > - even for argument types, to my eyes it’s now easier to read To my mind, the eye is still drawn to the arrows, and the readability is no better. And the parentheses give me a lisp vibe, for reasons I can't really pin down but which makes this version *less* readable. > An added bonus is we no longer have to think about double-arrows when a > callable type is in the return position of a function, e.g.: > ``` > def f() -> (int, str -> bool): ... > ``` Still looks like double arrows to me, I'm afraid. The parentheses don't group strongly enough to override the "chain of arrows" impression. > And it solves another major usability problem we found - writing optional > callables - because it’s now no problem at all to write > ``` > (int, str -> bool) | None > ``` > as the type of an optional callable argument. I guess, but it feels like punctuation
[Python-Dev] Re: RFC on Callable Syntax PEP
I've been thinking about readability hard because I share many of your concerns about readability. I'm starting to think parenthesizing the outside might work much better in practice: ``` (int, str -> bool) ``` instead of ``` (int, str) -> bool ``` This looks a bit less familiar, but it - eliminates any situation - helps the eye group together functions (and lets us use an editor's go-to-delimiter if we get lost!) An example = The function To get at what I mean, here's a nice simple function: ``` def zip(f, g): def zipped(x: int, y: str): return f(x), g(y) return zipped ``` typing.Callable Here's it's type using typing.Callable: ``` typing.Callable[ [typing.Callable[[int], bool], typing.Callable[[str], float]], typing.Callable[[int, str], tuple[bool, float] ] ``` which seems ugly. It's actually not bad compared to a lot of production code, but this is the kind of thing that led to PEP 677. current PEP 677 proposal -- With the current PEP 677 proposal, writing the type on one line we get ``` ((int) -> float, (str) -> bool) -> (int, str) -> tuple[float, bool] ``` I prefer this to the Callable version. But it’s dense, and I do agree it illustrates some readability issues with PEP 677. Using (int, str -> bool) syntax Here’s the type if we change the syntax to put the right parenthesis after the return type: ``` ((int -> float), (str -> bool) -> (int, str -> tuple[float, bool]) ``` To my eyes, most of the pain points are now eliminated. - there’s never a double-arrow due to callable in return position - even for argument types, to my eyes it’s now easier to read An added bonus is we no longer have to think about double-arrows when a callable type is in the return position of a function, e.g.: ``` def f() -> (int, str -> bool): ... ``` And it solves another major usability problem we found - writing optional callables - because it’s now no problem at all to write ``` (int, str -> bool) | None ``` as the type of an optional callable argument. New edge cases / readability issues? - I’m pretty sure *all* existing edge cases and readability issues are basically solved by this syntax because the grouping becomes obvious. The only new edge case I can see is that we might not like `(-> bool)` for parameterless callables. I’d be okay with that, but I’d also be down with a hack like `(() -> bool)`. I don’t actually think it matters much - by making this change we would trade multiple edge cases in *complicated* examples for a single edge case in the *simplest possible* example where readability isn’t a big problem. ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/AXRKGCPP2GTDRINQ6NQYM743Y6EH6FO5/ Code of Conduct: http://python.org/psf/codeofconduct/