Тёмный
No video :(

structural subtyping in python with Protocol! (intermediate) anthony explains  

anthonywritescode
Подписаться 40 тыс.
Просмотров 10 тыс.
50% 1

today I talk about one of my favorite additions to typing: Protocol! in this we extend from a previous example where we used overload to more-properly support any "__index__"-able type!
- intro to typing: • introduction to python...
- previous video on overload: • python typing: @overlo...
playlist: www.youtube.co...
==========
twitch: / anthonywritescode
dicsord: / discord
twitter: / codewithanthony
github: github.com/aso...
stream github: github.com/ant...
I won't ask for subscriptions / likes / comments in videos but it really helps the channel. If you have any suggestions or things you'd like to see please comment below!

Опубликовано:

 

19 авг 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 20   
@alsonyang230
@alsonyang230 Год назад
I know this is quite a late comment but amazing video as always. I only found out your channel about a few weeks ago, and just keep randomly watching your historical videos and learn heaps from it. The best python video on youtube for intermediate to advanced topics imo. I have a question in regards to implementing an interface, hoping you could give me some guidance. How would you choose between using `abc` and `protocol`? What are the factors in your consideration? For example, I know if there is a inheriting requirements (eg. I want to implement a template pattern in the parent class (interface) so that all the child classes can use the same methods), then `abc` should be the conventional way to go (although I can still inherit from a parent class using protocol, but it's not designed for it I suppose). Other than this, what are other considerations in choosing between abc and interface? something like if ..., I should use `abc`, elIf ..., I should use `protocol`, else: prefer `protocol` over `abc` (or vice versa)?
@marco_gorelli
@marco_gorelli 3 года назад
Amazing, thanks! If you made a course on type annotations I'm sure I'm not the only one who'd pay good money for it
@anthonywritescode
@anthonywritescode 3 года назад
yeah I should probably put something together -- I don't know where I'd host it though :thinking:
@sadhlife
@sadhlife 3 года назад
@@anthonywritescode try applying for scrimba.com, if brython somehow has mypy support it's a great platform, otherwise udemy ftw
@marco_gorelli
@marco_gorelli 3 года назад
@@anthonywritescode talk python to me? udemy?
@heitorlessa2715
@heitorlessa2715 2 года назад
Heck yeah
@sadhlife
@sadhlife 3 года назад
i guess you forgot to mention you need to do from __future__ import annotations or wrap your protocol class name in a string for it to work?
@anthonywritescode
@anthonywritescode 3 года назад
you don't need to do that? it works fine without it (as demonstrated)
@sadhlife
@sadhlife 3 года назад
@@anthonywritescode hmmm, when does it complain when using the same class name inside itself? I've definitely had it happen before
@anthonywritescode
@anthonywritescode 3 года назад
ohhhh for cycles yeah
@hielke2332
@hielke2332 3 года назад
Yes, this is "Postponed evaluation of Annotations". Basically, Python cannot use something that is not yet defined (even if you use it in its definition). One work around (as seen in the KD tree implementation) is to stringify the object you reference. This will not be necessary anymore in Python 3.10 and you can do that import if you already want to use this new behavior in older versions of Python. www.python.org/dev/peps/pep-0563/
@OrCarmi
@OrCarmi 2 года назад
Thank you for another great video! Is there a benefit for using a Protocol for an interface as opposed inheriting an ABC?
@anthonywritescode
@anthonywritescode 2 года назад
abc is runtime and protocol is typing time
@anthonywritescode
@anthonywritescode 2 года назад
(imo: never use abc)
@OrCarmi
@OrCarmi 2 года назад
@@anthonywritescode I'm not sure I get that. If you define an ABC and type it, won't you get the same benefits as a protocol with the defined inherited behaviour?
@anthonywritescode
@anthonywritescode 2 года назад
you have to explicitly register or inherit from an abc for it to be useful -- and it adds runtime overhead. neither of which happen with a Protocol which is "inherited" purely by having the same shape
@OrCarmi
@OrCarmi 2 года назад
@@anthonywritescode I see. Thanks for the explanation!
@horseinthesky
@horseinthesky 2 года назад
Hello. Could you please clarify the proper way of annotating for a dict of classes each of which must implement Protocol is? Here is an example: ``` from typing import NoReturn, Protocol from .ce import CEDriver from .mellanox import MellanoxDriver class SupportsGetSet(Protocol): def get_state(self) -> str: ... def set_state(self, desired_stete: str) -> NoReturn: ... driver_map: dict[str, SupportsGetSet] = { "huawei": CEDriver, "mellanox": MellanoxDriver, } ``` In this case, mypy yells at me with: ``` endpoints/vlantoggler/driver/__init__.py:18: error: Dict entry 0 has incompatible type "str": "Type[CEDriver]"; expected "str": "SupportsGetSet" endpoints/vlantoggler/driver/__init__.py:19: error: Dict entry 1 has incompatible type "str": "Type[MellanoxDriver]"; expected "str": "SupportsGetSet" ``` This is understandable since it expects an object which implements Protocol. So if I do this: ``` driver_map: dict[str, Type[SupportsGetSet]] = { "huawei": CEDriver, "mellanox": MellanoxDriver, } ``` mypy becomes happy at this point but yells at me when I actually call a class: ``` endpoints/vlantoggler/api.py:97: error: Unexpected keyword argument "host" for "SupportsGetSet" endpoints/vlantoggler/api.py:97: error: Unexpected keyword argument "interface" for "SupportsGetSet" endpoints/vlantoggler/api.py:97: error: "SupportsGetSet" has no attribute "__aenter__" endpoints/vlantoggler/api.py:97: error: "SupportsGetSet" has no attribute "__aexit__" ``` So it is like it expects me to describe __init__ and __aenter__/__aexit__ which I don't relly want to do :P I even tried to use a bounded TypeVar: ``` PortSwitcherDriver = TypeVar("PortSwitcherDriver", bound=SupportsGetSet) driver_map: dict[str, PortSwitcherDriver] = { "huawei": CEDriver, "mellanox": MellanoxDriver, } ``` but now it says: ``` endpoints/vlantoggler/driver/__init__.py:17: error: Type variable "vlantoggler.driver.PortSwitcherDriver" is unbound endpoints/vlantoggler/driver/__init__.py:17: note: (Hint: Use "Generic[PortSwitcherDriver]" or "Protocol[PortSwitcherDriver]" base class to bind "PortSwitcherDriver" inside a class) endpoints/vlantoggler/driver/__init__.py:17: note: (Hint: Use "PortSwitcherDriver" in function signature to bind "PortSwitcherDriver" inside a function) ``` What is the right way to achieve the goal? Thank you in advance =)
@anthonywritescode
@anthonywritescode 2 года назад
you would have to describe `__init__` and such. mypy can't magically know that a particular string means a particular class. also `NoReturn` is almost certainly not what you want -- ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE--zH0qqDtd4w.html
@horseinthesky
@horseinthesky 2 года назад
​@@anthonywritescode This escalates quickly =) I've implemented `__init__`. Then if I use object in async context manager with `async with` it asks me to implement `__aenter__/__aexit__`. If I do so ``` class SupportsGetSet(Protocol): def __init__(self, host: str, interface: Interface) -> None: ... async def __aenter__(self) -> Awaitable[Any]: ... async def __aexit__(self, *exception) -> None: ... def get_state(self) -> str: ... def set_state(self, desired_stete: str) -> None: ... ``` it says: ``` endpoints/vlantoggler/api.py:159: error: "Awaitable[Any]" has no attribute "get_state" endpoints/vlantoggler/api.py:236: error: "Awaitable[Any]" has no attribute "set_state" ```
Далее
ЛИЗА - СПАСАТЕЛЬ😍😍😍
00:25
Просмотров 1 млн
Protocol Or ABC In Python - When to Use Which One?
23:45
You Can Do Really Cool Things With Functions In Python
19:47
ЛИЗА - СПАСАТЕЛЬ😍😍😍
00:25
Просмотров 1 млн