4 ms·
Why do you say that duck typing is simplified structural typing? Its relationship with structural typing is on a different axis. Duck typing is its dynamic-typi
by networked 1y ago
Why do you say that duck typing is simplified structural typing?
Its relationship with structural typing is on a different axis.
Duck typing is its dynamic-typing counterpart.
Python does support structural typing through protocols introduced in version 3.8.
They are documented in https://typing.python.org/en/latest/spec/protocol.html https://typing.python.org/en/latest/spec/protocol.html.
As a demo, here is part of https://www.typescriptlang.org/play/typescript/language/structural-typing.ts.html https://www.typescriptlang.org/play/typescript/language/stru... translated to Python:
from dataclasses import dataclass
from typing import Protocol
class Globular(Protocol):
diameter: float
class Spherical(Protocol):
diameter: float
# In Python, we need to define concrete classes that implement the protocols.
@dataclass
class Ball:
diameter: float
@dataclass
class Sphere:
diameter: float
ball: Globular = Ball(diameter=10)
sphere: Spherical = Sphere(diameter=20)
# These assignments work because both types structurally conform to the protocols.
sphere = ball
ball = sphere
class Tubular(Protocol):
diameter: float
length: float
@dataclass
class Tube:
diameter: float
length: float
tube: Tubular = Tube(diameter=12, length=3)
tube = ball # Fail type check.
ball = tube # Passes.
This is what Pyright says about it:
Found 1 error.
/scratch/structural.py
/scratch/structural.py:37:8 - error: Type "Ball" is not assignable to declared type "Tubular"
"Ball" is incompatible with protocol "Tubular"
"length" is not present (reportAssignmentType)
1 error, 0 warnings, 0 informations
Edit: And this is ty:
error: lint:invalid-assignment: Object of type `Ball` is not assignable to `Tubular`
--> structural.py:37:1
|
35 | tube: Tubular = Tube(diameter=12, length=3)
36 |
37 | tube = ball # Fail type check.
| ^^^^
38 | ball = tube # Passes.
|
info: `lint:invalid-assignment` is enabled by default
Found 1 diagnostic
- bunderbunder 1y agoI'd go a step further and say that duck typing is more than just structural typing's dynamic counterpart. Because, again, that's confounding two different axes. Dynamic vs static describes when type checking happens and whether types are associated with names or with values. But it doesn't necessarily describe the definition of "type". The real difference between structural typing and duck typing is that structural typing requires all of a type's declared members to be present for an object to be considered compatible. Duck typing only requires the members that are actually being accessed to be present. This is definitely more common in dynamic languages, but I'm not aware of any particular reason why that kind of checking couldn't also be done statically.
- maleldil 1y agoIf I understand correctly, defining the protocol like this forces the implementation classes to have the members as proper fields and disallows properties. If you define `diameter` as a property in the protocol, it supports both: from dataclasses import dataclass from typing import Protocol class Field(Protocol): diameter: float class Property(Protocol): @property def diameter(self) -> float: ... class Ball: @property def diameter(self) -> float: return 1 @dataclass class Sphere: diameter: float ball_field: Field = Ball() sphere_field: Field = Sphere(diameter=20) ball_prop: Property = Ball() sphere_prop: Property = Sphere(diameter=20) Pyright output: /Users/italo/dev/paper-hypergraph/t.py /Users/italo/dev/paper-hypergraph/t.py:27:21 - error: Type "Ball" is not assignable to declared type "Field" "Ball" is incompatible with protocol "Field" "diameter" is invariant because it is mutable "diameter" is an incompatible type "property" is not assignable to "float" (reportAssignmentType) 1 error, 0 warnings, 0 information That is to say, I find Python's support for structural typing to be limited in practice.