python / python/typing

Ability to use Callable type alias when annotating functions

Đang mở
#1,419 3 bình luận 9 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

topic: feature
Ngôn ngữ chính
Python
Star
1.8k
Fork
302
Merge trung bình
23 giờ
Pull request đã merge (30 ngày)
8

Mô tả

Hello. I would like to revive the discussion about Callable type aliases. The original discussion is here, and the related discussion about @declared_type is here and here.

The original thread contains a great example of the problem and a proposed solution:

from typing import Callable
import math

ActivationFunction = Callable[[float], float]

sigmoid: ActivationFunction
def sigmoid(x):
     return 1 / (1 + math.exp(-x))

relu: ActivationFunction
def relu(x):
     return max(0, x)

Another prosed solution is to use the @declared_type decorator:

@declared_type(ActivationFunction)
def sigmoid(x):
     return 1 / (1 + math.exp(-x))

@declared_type(ActivationFunction)
def relu(x):
     return max(0, x)

Currently, this can be done with Protocols, but it's too verbose:

from typing import Protocol
import math

class ActivationFunction(Protocol):
    def __call__(self, x: float) -> float:
        ...

class Sigmoid(ActivationFunction):
    def __call__(self, x: float) -> float:
        return 1 / (1 + math.exp(-x))

class Relu(ActivationFunction):
    def __call__(self, x: float) -> float:
        return max(0, x)

sigmoid = Sigmoid()
relu = Relu()

print(sigmoid(0.5))
print(relu(0.5))

If the function is a single expression, it can be done very nicely with lambdas:

from typing import Callable
import math

ActivationFunction = Callable[[float], float]

sigmoid: ActivationFunction = lambda x: 1 / (1 + math.exp(-x))
relu: ActivationFunction = lambda x: max(0, x)

print(sigmoid(0.5))
print(relu(0.5))

Here's the equivalent FSharp code, with the only difference being that FSharp supports multiline lambdas:

type ActivationFunction = float -> float

let sigmoid: ActivationFunction = fun x -> 1.0 / (1.0 + exp(-x))
let relu: ActivationFunction = fun x -> max 0.0 x

printfn "%f" (sigmoid 0.5)
printfn "%f" (relu 0.5)

I'm asking about this feature because I'm reading a book called Domain Modeling Made Functional by Scott Wlaschin. In this book, the author recommends modeling the domain with types, including function type aliases, and focusing on the implementation details later. Here's an example from Chapter 9:

Domain_Modeling_Made_Functional

I'd like to try a similar approach in Python. Has there been any further discussion about this topic, or is there a workaround I'm unaware of? Thank you!

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu bằng cách đọc các cuộc thảo luận được liên kết trong các issue 1641, 2087 và pull request 3291, sau đó so sánh các cách tiếp cận được đề xuất là bí danh Callable và @declared_type với workaround Protocol được trình bày ở đây. Công việc chỉ được coi là hoàn tất khi có một hành vi được lựa chọn và chấp nhận rõ ràng cho việc chú thích các định nghĩa hàm, cùng với công việc triển khai và xác thực tương ứng; issue này không nêu tên tệp hoặc test.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
devtools
Loại issue
Tính năng
Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Cần làm rõ
Mức phù hợp với người mới
25/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.