Three Ways To Match A Duck

Person never inherits from Bird or Quacker:

from typing import Protocol, runtime_checkable
from abc import ABC, abstractmethod

class Bird(ABC):
    @abstractmethod
    def quack(self) -> str: ...

@runtime_checkable
class Quacker(Protocol):
    def quack(self) -> str: ...

class Person:
    def quack(self) -> str:
        return "I'm quacking!"

def make_it_quack(obj) -> str:
    return obj.quack()

p = Person()
print(make_it_quack(p))
print(isinstance(p, Bird))
print(isinstance(p, Quacker))

What does this print, in order, and why does the second line differ from the third?

A

I'm quacking!, False, False

B

I'm quacking!, False, True

C

I'm quacking!, True, True

D

Raises AttributeError before printing