Hành vi dấu hai chấm kỳ lạ này đang làm gì?


104

Tôi đang sử dụng Python 3.6.1 và tôi đã gặp một thứ rất lạ. Tôi có một lỗi chính tả bài tập từ điển đơn giản khiến tôi mất nhiều thời gian để tìm.

context = {}
context["a"]: 2
print(context)

Đầu ra

{}

context["a"]: 2đang làm gì? Nó không nâng cao một SyntaxErrorkhi nó nên IMO. Lúc đầu, tôi nghĩ nó đang tạo ra một lát cắt. Tuy nhiên, đánh máy repr(context["a"]: 2)làm tăng a SyntaxError. Tôi cũng đã gõ context["a"]: 2vào bảng điều khiển và bảng điều khiển không in bất cứ điều gì. Tôi nghĩ có thể nó quay trở lại None, nhưng tôi không chắc lắm.

Tôi cũng đã nghĩ rằng nó có thể là một câu lệnh if một dòng, nhưng đó cũng không phải là cú pháp đúng.

Ngoài ra, context["a"]nên nâng cao a KeyError.

Tôi đang bối rối. Điều gì đang xảy ra?


2
Câu hỏi này đã có một bản dupe và rõ ràng là điều này gây nhầm lẫn cho người mới sử dụng Python. Tôi đoán điều này là tồi tệ nhất nếu Python là ngôn ngữ duy nhất của bạn, nơi gợi ý kiểu và định nghĩa biến trước khi khởi tạo nói chung có thể cảm thấy xa lạ. Tôi cho rằng việc tăng lỗi là không thể vì hành vi này là cố ý và đôi khi hữu ích như được giải thích trong PEP 526 và bạn không muốn phá vỡ khả năng tương thích. Tuy nhiên, tôi tự hỏi liệu các nhà phát triển Python có cân nhắc việc thêm một thông báo cảnh báo hữu ích cho một số trường hợp hay không.
Chris_Rands

1
Điều này có trả lời câu hỏi của bạn không? Chú thích biến trong Python 3.6 là gì?
Georgy

Câu trả lời:


98

Bạn đã vô tình viết một chú thích biến đúng về mặt cú pháp . Tính năng đó đã được giới thiệu trong Python 3.6 (xem PEP 526 ).

Mặc dù chú thích biến được phân tích cú pháp như một phần của phép gán có chú thích , câu lệnh gán là tùy chọn :

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

Do đó trong context["a"]: 2

  • context["a"] là mục tiêu chú thích
  • 2 chính là chú thích
  • context["a"] không được giám sát

PEP tuyên bố rằng "mục tiêu của chú thích có thể là bất kỳ mục tiêu chuyển nhượng đơn hợp lệ nào, ít nhất là về mặt cú pháp (tùy thuộc vào trình kiểm tra loại phải làm gì với điều này)" , có nghĩa là khóa không cần tồn tại để chú thích (do đó không có KeyError). Đây là một ví dụ từ PEP ban đầu:

d = {}
d['a']: int = 0  # Annotates d['a'] with int.
d['b']: int      # Annotates d['b'] with int.

Thông thường, biểu thức chú thích nên đánh giá thành kiểu Python - sau khi tất cả, công dụng chính của chú thích là gợi ý kiểu, nhưng nó không được thực thi. Chú thích có thể là bất kỳ biểu thức Python hợp lệ nào , bất kể kiểu hoặc giá trị của kết quả.

Như bạn có thể thấy, tại thời điểm này, các gợi ý về kiểu rất dễ dãi và hiếm khi hữu ích, trừ khi bạn có một trình kiểm tra kiểu tĩnh như mypy .


12
Sau đó điều này không yêu cầu một =toán tử gán? Chìa khóa không tồn tại. Điều này chỉ cảm thấy sai đối với tôi.
justengel

1
Trong trường hợp này, : toán tử gán. Chúng tôi chỉ "chỉ định" một loại chú thích, không phải một khóa. Tôi nghi ngờ có bất kỳ lý do gì để cho phép nó, chỉ là một tác động ngoài ý muốn của việc thêm cú pháp chú thích.
chepner

1
@chepner Có vẻ như đây không phải là imho tác dụng phụ. Đây chính xác là những gì mà PEP tương ứng được thiết kế để làm.
Ma0

6
Thật kỳ lạ là nó sẽ cho phép bạn chú thích một mục tiêu chưa được xác định. Nếu dòng đầu tiên của tôi là x: strvà ngay sau đó type(x), thông dịch viên sẽ tăng a NameError. IMO cú pháp nên thực thi đối tượng được xác định trước hoặc được xác định ngay tại chỗ. Điều này chỉ giới thiệu sự nhầm lẫn.
r.ook

2
@Idlehands Mặc dù vậy, điều này sẽ đánh bại mục đích. Có x = 'i am a string'trước x: strlàm cho loại sau thừa .. Điều này không nên được thêm vào chút nào. Nó là tốt như bình luận; Tôi không bao giờ cho thấy nó được sử dụng theo cách này hay cách khác.
Ma0
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.