We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Interfaces with Protocols and ABCs step 6 of 26
Inherit a Default Method from a Protocol
A class can fit a protocol in two ways. It can match the protocol's members, or it can inherit from the protocol like any other base class. This exercise shows what each way gives you.
The supplied Runner protocol lists run, and it also has a method with a
body:
class Runner(Protocol):
def run(self, payload: str) -> str: ...
def run_twice(self, payload: str) -> str:
return self.run(self.run(payload))
Only inheriting gives a class the protocol's code
- A class that only matches
Runnergets nothing from it. To fit, it needs its ownrun_twice. - A class that inherits from
Runnergetsrun_twicethrough ordinary inheritance. - If a class such as
Missinginherits fromRunnerbut leaves outrun, mypy treatsrunas abstract and rejectsMissing(). Python still creates the object, becauserunhas no@abstractmethoddecorator. Calling itsrunreturnsNone, whatever the annotation says. - Mark a protocol method with
@abstractmethod, and Python also refuses to create the object, as it does for an ABC.
What to write
Implicitdoes not inherit fromRunner. Itsrunreturnspayload.upper(). Add arun_twicethat returnsself.run(self.run(payload)). Without it, mypy rejectsImplicit()as aRunner, because therun_twicemember is missing.Explicit(Runner)has arunthat appends".". Keep its@override, and do not definerun_twice.- Leave
Missing(Runner)empty, and leaveAbcMissing(AbcRunner)as it is.AbcRunner.runhas@abstractmethod. try_build(cls: type) -> strcallscls(). Return"TypeError"if that raisesTypeError, and"constructed"otherwise. Keep the parameter as plaintype, so that mypy lets you pass a class it considers abstract.solve(payload)createsrunners: list[Runner] = [Implicit(), Explicit()]and returns this dictionary:
| Key | Value |
|---|---|
"outputs" |
[runner.run_twice(payload) for runner in runners] |
"explicit_inherits_default" |
Explicit.run_twice is Runner.run_twice |
"implicit_inherits_default" |
Implicit.run_twice is Runner.run_twice |
"protocol_subclass_abstracts" |
sorted(Missing.__abstractmethods__) |
"abc_subclass_abstracts" |
sorted(AbcMissing.__abstractmethods__) |
"protocol_subclass_build" |
try_build(Missing) |
"abc_subclass_build" |
try_build(AbcMissing) |
What the report shows
For payload="ab", the outputs are ["AB", "ab.."]. The two is checks
compare function objects. Explicit.run_twice is the protocol's own
function, so the first check is True. Implicit.run_twice is a separate
function, so the second is False.
Missing.__abstractmethods__ is empty, so try_build(Missing) returns
"constructed". AbcMissing.__abstractmethods__ holds "run", so
try_build(AbcMissing) returns "TypeError". mypy calls both classes
abstract, but only the decorated method stops Python from creating one.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.