Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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.

As a demo, here is part of 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


I'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.


If 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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: