Thêm giá trị tham số mặc định với gợi ý loại trong Python


233

Nếu tôi có một chức năng như thế này:

def foo(name, opts={}):
  pass

Và tôi muốn thêm gợi ý loại cho các tham số, làm thế nào để tôi làm điều đó? Cách tôi giả sử cho tôi một lỗi cú pháp:

def foo(name: str, opts={}: dict) -> str:
  pass

Sau đây không gây ra lỗi cú pháp nhưng có vẻ như không phải là cách trực quan để xử lý trường hợp này:

def foo(name: str, opts: dict={}) -> str:
  pass

Tôi không thể tìm thấy bất cứ điều gì trong typingtài liệu hoặc trên một tìm kiếm Google.

Chỉnh sửa: Tôi không biết các đối số mặc định hoạt động như thế nào trong Python, nhưng vì câu hỏi này, tôi sẽ giữ các ví dụ ở trên. Nói chung, tốt hơn nhiều là làm như sau:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass

4
Chức năng cuối cùng là cách chính xác. Nó cũng giống như scalangôn ngữ.
Israel Unterman

14
bạn có một loại mặc định có thể thay đổi - điều đó sẽ dẫn đến các vấn đề
noɥʇʎԀʎzɐɹƆ

xem câu trả lời cập nhật của tôi, @josh
noɥʇʎԀʎzɐɹƆ

@ noɥʇʎԀʎzɐɹƆ Không trừ khi bạn sử dụng nó, ví dụ như ghi nhớ. : P
Mateen Ulhaq

Câu trả lời:


279

Cách thứ hai của bạn là chính xác.

def foo(opts: dict = {}):
    pass

print(foo.__annotations__)

đầu ra này

{'opts': <class 'dict'>}

Đúng là nó không được liệt kê trong PEP 484 , nhưng gợi ý loại là một ứng dụng của chú thích chức năng, được ghi lại trong PEP 3107. Phần cú pháp làm rõ rằng các đối số từ khóa hoạt động với chú thích chức năng theo cách này.

Tôi khuyên bạn không nên sử dụng các đối số từ khóa có thể thay đổi. Thêm thông tin ở đây .


1
Xem legacy.python.org/dev/peps/pep-3107/#syntax . Gợi ý kiểu chỉ là một ứng dụng của chú thích chức năng.
chepner

@chepner đúng. không biết rằng PEP 3107 có gì đó về các đối số từ khóa.
noɥʇʎԀʎzɐɹƆ

2
Ồ, tôi không biết về các đối số mặc định có thể thay đổi trong Python ... đặc biệt là đến từ Javascript / Ruby nơi các đối số mặc định hoạt động khác nhau. Sẽ không làm lại những gì đã được nói về quảng cáo xung quanh SO về nó, tôi chỉ vui mừng vì tôi đã phát hiện ra điều này trước khi nó cắn tôi. Cảm ơn!
Josh

6
Tôi luôn được khuyên nên sử dụng Không thay vì một loại có thể thay đổi như {} hoặc [] hoặc một đối tượng mặc định làm đột biến cho đối tượng đó mà không có bản sao sâu sẽ tồn tại giữa các lần lặp.
MrMesees

2
xác định đủ chức năng với các đối số từ khóa có thể thay đổi và chỉ là vấn đề thời gian trước khi bạn thấy mình nhìn lại phiên gỡ lỗi 4 giờ đặt câu hỏi về lựa chọn cuộc sống của bạn
Joseph Sheedy

20

Nếu bạn đang sử dụng cách (được giới thiệu trong Python 3.5), bạn có thể sử dụng typing.Optional, nơi Optional[X]tương đương với Union[X, None]. Nó được sử dụng để báo hiệu rằng giá trị rõ ràng Noneđược cho phép. Từ gõ. Hấp thụ :

def foo(arg: Optional[int] = None) -> None:
    ...

2
Nên không có được không khoảng trắng xung quanh =trong Optional[int] = Nonenhư nó là ước cho các đối số từ khóa không kiểu gợi ý?
fact_panda

7

Gần đây tôi đã thấy một lớp lót này:

def foo(name: str, opts: dict=None) -> str:
    opts = {} if not opts else opts
    pass

Xin chào @Kirkalicy, cảm ơn câu trả lời của bạn. Bạn có thể giải thích làm thế nào nó hoạt động?
Nathan

1
Dict trống được truyền dưới dạng tham số mặc định là cùng một dict cho mỗi cuộc gọi. Vì vậy, nếu hàm biến đổi nó thì lần sau mặc định sẽ là giá trị bị đột biến so với lần trước. Đặt Nonemặc định và sau đó kiểm tra bên trong phương thức sẽ tránh được vấn đề này bằng cách phân bổ một lệnh mới mỗi khi phương thức được gọi.
Ian Goldby
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.