Tài liệu này nhằm mô tả cú pháp của trình trang trí và quy trình dẫn đến các quyết định được đưa ra. Nó không cố gắng bao gồm số lượng lớn các cú pháp thay thế tiềm năng, cũng không cố gắng liệt kê đầy đủ tất cả các mặt tích cực và tiêu cực của từng dạng
trừu tượng
Phương thức hiện tại để chuyển đổi các hàm và phương thức [ví dụ: khai báo chúng dưới dạng một lớp hoặc phương thức tĩnh] rất khó xử và có thể dẫn đến mã khó hiểu. Lý tưởng nhất là các phép biến đổi này phải được thực hiện tại cùng một điểm trong mã mà bản thân việc khai báo được thực hiện. PEP này giới thiệu cú pháp mới để chuyển đổi khai báo hàm hoặc phương thức
Động lực
Phương pháp hiện tại áp dụng một phép biến đổi cho một hàm hoặc phương thức đặt phép biến đổi thực tế sau thân hàm. Đối với các chức năng lớn, điều này tách một thành phần chính trong hành vi của chức năng khỏi định nghĩa của phần còn lại của giao diện bên ngoài của chức năng. Ví dụ
def foo[self]: perform method operation foo = classmethod[foo]
Điều này trở nên khó đọc hơn với các phương thức dài hơn. Có vẻ như ít hơn Pythonic khi đặt tên hàm ba lần cho một khai báo về mặt khái niệm. Một giải pháp cho vấn đề này là di chuyển sự biến đổi của phương thức gần hơn với khai báo của chính phương thức đó. Mục đích của cú pháp mới là để thay thế
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
với một giải pháp thay thế đặt trang trí trong khai báo của hàm
@classmethod @synchronized[lock] def foo[cls]: pass
Việc sửa đổi các lớp theo cách này cũng có thể thực hiện được, mặc dù lợi ích không rõ ràng ngay lập tức. Gần như chắc chắn, bất cứ điều gì có thể được thực hiện với các trình trang trí lớp đều có thể được thực hiện bằng cách sử dụng siêu dữ liệu, nhưng việc sử dụng siêu dữ liệu đủ mơ hồ để có một số điểm thu hút để có một cách dễ dàng hơn để thực hiện các sửa đổi đơn giản đối với các lớp. Đối với Trăn 2. 4, chỉ các trình trang trí hàm/phương thức mới được thêm vào
PEP 3129 đề xuất thêm các trình trang trí lớp kể từ Python 2. 6
Tại sao nó lại khó thế này?
Hai trình trang trí [
@classmethod @synchronized[lock] def foo[cls]: pass4 và
@classmethod @synchronized[lock] def foo[cls]: pass5] đã có sẵn trong Python kể từ phiên bản 2. 2. Người ta cho rằng kể từ khoảng thời gian đó, một số hỗ trợ cú pháp cho chúng cuối cùng sẽ được thêm vào ngôn ngữ. Với giả định này, người ta có thể thắc mắc tại sao lại khó đi đến thống nhất. Các cuộc thảo luận đã diễn ra gay gắt vào những thời điểm trong cả hai comp. lang thang. python và danh sách gửi thư python-dev về cách tốt nhất để triển khai các trình trang trí chức năng. Không có một lý do rõ ràng tại sao điều này nên như vậy, nhưng một số vấn đề dường như gây chia rẽ nhất
- Bất đồng về vị trí của “tuyên bố ý định”. Hầu hết mọi người đều đồng ý rằng việc trang trí/chuyển đổi một chức năng ở cuối định nghĩa của nó là không tối ưu. Ngoài ra, dường như không có sự đồng thuận rõ ràng về nơi đặt thông tin này
- Ràng buộc cú pháp. Python là một ngôn ngữ đơn giản về mặt cú pháp với các ràng buộc khá chặt chẽ về những gì có thể và không thể thực hiện được nếu không “làm rối tung mọi thứ lên” [cả về mặt trực quan và liên quan đến trình phân tích cú pháp ngôn ngữ]. Không có cách rõ ràng nào để cấu trúc thông tin này sao cho những người mới làm quen với khái niệm này sẽ nghĩ, “Ồ, tôi biết bạn đang làm gì. ” Điều tốt nhất có thể là ngăn người dùng mới tạo ra một mô hình tinh thần cực kỳ sai lầm về ý nghĩa của cú pháp
- Nhìn chung không quen thuộc với khái niệm. Đối với những người đã từng làm quen với đại số [hoặc thậm chí là số học cơ bản] hoặc đã sử dụng ít nhất một ngôn ngữ lập trình khác, phần lớn Python là trực quan. Rất ít người có bất kỳ kinh nghiệm nào với khái niệm decorator trước khi bắt gặp nó trong Python. Không có meme tồn tại mạnh mẽ nào có thể nắm bắt được khái niệm này
- Các cuộc thảo luận về cú pháp nói chung dường như gây ra nhiều tranh cãi hơn hầu hết mọi thứ khác. Độc giả được chỉ đến các cuộc thảo luận của nhà điều hành ternary được liên kết với PEP 308 để biết thêm ví dụ về điều này
Lý lịch
Có một thỏa thuận chung rằng hỗ trợ cú pháp là mong muốn đối với tình trạng hiện tại. Guido đã đề cập đến hỗ trợ cú pháp cho các nhà trang trí trong bài thuyết trình quan trọng về DevDay của anh ấy tại Hội nghị Python lần thứ 10, mặc dù sau đó anh ấy nói rằng đó chỉ là một trong số các tiện ích mở rộng mà anh ấy đã đề xuất ở đó “một cách nửa đùa nửa thật”. Michael Hudson đã nêu chủ đề trên
@classmethod @synchronized[lock] def foo[cls]: pass6 ngay sau hội nghị, quy kết cú pháp ban đầu trong ngoặc đơn cho một đề xuất trước đó trên
@classmethod @synchronized[lock] def foo[cls]: pass7 của Gareth McCaughan
Trang trí lớp có vẻ như là một bước tiếp theo rõ ràng vì định nghĩa lớp và định nghĩa hàm giống nhau về mặt cú pháp, tuy nhiên Guido vẫn chưa thuyết phục và các trình trang trí lớp gần như chắc chắn sẽ không có trong Python 2. 4
Cuộc thảo luận tiếp tục diễn ra trên python-dev từ tháng 2 năm 2002 đến tháng 7 năm 2004. Hàng trăm và hàng trăm bài đăng đã được thực hiện, với những người đề xuất nhiều biến thể cú pháp có thể. Guido đã lấy một danh sách các đề xuất cho EuroPython 2004, nơi diễn ra một cuộc thảo luận. Sau đó, anh ấy quyết định rằng chúng tôi sẽ có cú pháp @decorator kiểu Java và cú pháp này xuất hiện lần đầu tiên trong 2. 4a2. Barry Warsaw đặt tên cho cú pháp này là 'pie-decorator', để tôn vinh vụ đấu súng Pie-thon Parrot xảy ra cùng thời điểm với cú pháp decorator và bởi vì @ trông hơi giống một chiếc bánh. Guido đã phác thảo trường hợp của mình trên Python-dev, bao gồm phần này trên một số [nhiều] biểu mẫu bị từ chối
Trên tên 'Decorator'
Đã có một số phàn nàn về việc chọn tên 'trang trí' cho tính năng này. Vấn đề chính là cái tên này không phù hợp với việc sử dụng nó trong sách GoF. Cái tên 'decorator' có lẽ được sử dụng nhiều hơn trong khu vực trình biên dịch - một cây cú pháp được duyệt và chú thích. Rất có thể một cái tên hay hơn sẽ xuất hiện
Mục tiêu thiết kế
Cú pháp mới nên
- hoạt động cho các hàm bao tùy ý, bao gồm các hàm có thể gọi được do người dùng xác định và các nội trang hiện có
@classmethod @synchronized[lock] def foo[cls]: pass
4 và@classmethod @synchronized[lock] def foo[cls]: pass
5. Yêu cầu này cũng có nghĩa là cú pháp của trình trang trí phải hỗ trợ truyền đối số cho hàm tạo của trình bao bọc - làm việc với nhiều hàm bao cho mỗi định nghĩa
- làm cho nó rõ ràng những gì đang xảy ra;
- là một cú pháp “rằng… [là] dễ nhớ sau khi được giải thích”
- không làm cho các tiện ích mở rộng trong tương lai trở nên khó khăn hơn
- dễ gõ;
- không làm cho việc quét qua mã nhanh chóng trở nên khó khăn hơn. Vẫn phải dễ dàng tìm kiếm tất cả các định nghĩa, một định nghĩa cụ thể hoặc các đối số mà một hàm chấp nhận
- không phức tạp hóa các công cụ hỗ trợ phụ một cách không cần thiết như trình soạn thảo ngôn ngữ nhạy cảm và “công cụ phân tích cú pháp đồ chơi hiện có” khác
- cho phép các trình biên dịch trong tương lai tối ưu hóa cho các trình trang trí. Với hy vọng một trình biên dịch JIT cho Python sẽ ra đời vào một thời điểm nào đó, điều này có xu hướng yêu cầu cú pháp cho các bộ trang trí xuất hiện trước định nghĩa hàm
- di chuyển từ phần cuối của chức năng, nơi nó hiện đang bị ẩn, lên phía trước, nơi nó hiện rõ hơn trên khuôn mặt của bạn
Andrew Kuchling có liên kết đến một loạt các cuộc thảo luận về động cơ và trường hợp sử dụng trong blog của anh ấy. Đặc biệt đáng chú ý là danh sách các trường hợp sử dụng của Jim Huginin
Cú pháp hiện tại
Cú pháp hiện tại cho các trình trang trí chức năng như được triển khai trong Python 2. 4a2 là
@dec2 @dec1 def func[arg1, arg2, ...]: pass
Điều này tương đương với
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]0
không có phép gán trung gian cho biến
@dec2 @dec1 def func[arg1, arg2, ...]: pass0. Các bộ trang trí gần khai báo hàm. Dấu hiệu @ cho thấy rõ rằng có điều gì đó mới đang diễn ra ở đây
Lý do căn bản cho thứ tự ứng dụng [từ dưới lên trên] là nó phù hợp với thứ tự thông thường cho chức năng-ứng dụng. Trong toán học, thành phần của các hàm [g o f][x] chuyển thành g[f[x]]. Trong Python,
@dec2 @dec1 def func[arg1, arg2, ...]: pass1 dịch thành
@dec2 @dec1 def func[arg1, arg2, ...]: pass2
Câu lệnh trang trí bị giới hạn trong những gì nó có thể chấp nhận – các biểu thức tùy ý sẽ không hoạt động. Guido thích điều này vì cảm giác ruột thịt
Cú pháp hiện tại cũng cho phép các khai báo của trình trang trí gọi một hàm trả về một trình trang trí
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]4
Điều này tương đương với
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]5
Cơ sở lý luận để có một hàm trả về một trình trang trí là phần sau dấu @ có thể được coi là một biểu thức [mặc dù bị hạn chế về mặt cú pháp chỉ là một hàm] và bất kỳ biểu thức nào mà biểu thức đó trả về đều được gọi là. Xem các đối số khai báo
Cú pháp thay thế
Đã có một số lượng lớn các cú pháp khác nhau được đề xuất – thay vì cố gắng làm việc thông qua các cú pháp riêng lẻ này, bạn nên chia cuộc thảo luận về cú pháp thành một số lĩnh vực. Cố gắng thảo luận riêng lẻ từng cú pháp có thể sẽ là một hành động điên rồ và tạo ra một PEP hoàn toàn khó sử dụng
Vị trí trang trí
Điểm cú pháp đầu tiên là vị trí của các bộ trang trí. Đối với các ví dụ sau, chúng tôi sử dụng @syntax được sử dụng trong 2. 4a2
Các bộ trang trí trước câu lệnh def là lựa chọn thay thế đầu tiên và cú pháp được sử dụng trong 2. 4a2
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]6
Đã có một số ý kiến phản đối về vị trí này – lý do chính là đây là trường hợp Python thực sự đầu tiên mà một dòng mã có ảnh hưởng đến dòng tiếp theo. Cú pháp có sẵn trong 2. 4a3 yêu cầu một bộ trang trí trên mỗi dòng [trong a2, nhiều bộ trang trí có thể được chỉ định trên cùng một dòng] và quyết định cuối cùng cho 2. 4 cuối cùng ở lại một trang trí trên mỗi dòng
Mọi người cũng phàn nàn rằng cú pháp nhanh chóng trở nên khó sử dụng khi sử dụng nhiều bộ trang trí. Tuy nhiên, vấn đề được đưa ra là khả năng một số lượng lớn các bộ trang trí được sử dụng trên một chức năng duy nhất là nhỏ và do đó đây không phải là một vấn đề lớn.
Một số ưu điểm của hình thức này là các trình trang trí sống bên ngoài phần thân phương thức – rõ ràng chúng được thực thi tại thời điểm hàm được xác định
Một ưu điểm khác là tiền tố cho định nghĩa hàm phù hợp với ý tưởng biết về sự thay đổi đối với ngữ nghĩa của mã trước chính mã đó, do đó bạn biết cách diễn giải đúng ngữ nghĩa của mã mà không cần phải quay lại và thay đổi nhận thức ban đầu của mình nếu
Guido quyết định rằng anh ấy muốn có các bộ trang trí trên hàng trước 'def', vì có cảm giác rằng một danh sách đối số dài có nghĩa là các bộ trang trí sẽ bị 'ẩn'
Dạng thứ hai là các bộ trang trí giữa def và tên hàm hoặc tên hàm và danh sách đối số
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]7
Có một số phản đối đối với hình thức này. Đầu tiên là nó dễ dàng phá vỡ 'tính khả dụng' của nguồn - bạn không còn có thể tìm kiếm 'def foo[' và tìm định nghĩa của hàm. Phản đối thứ hai, nghiêm trọng hơn, là trong trường hợp có nhiều trình trang trí, cú pháp sẽ cực kỳ khó sử dụng
Hình thức tiếp theo, đã có một số người ủng hộ mạnh mẽ, là đặt các bộ trang trí giữa danh sách đối số và dấu
@dec2 @dec1 def func[arg1, arg2, ...]: pass3 trong dòng 'def'
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]9
Guido đã tóm tắt các lập luận chống lại biểu mẫu này [nhiều trong số đó cũng áp dụng cho biểu mẫu trước đó] như
- nó ẩn thông tin quan trọng [e. g. rằng nó là một phương thức tĩnh] sau chữ ký, nơi nó dễ bị bỏ qua
- rất dễ bỏ lỡ quá trình chuyển đổi giữa danh sách đối số dài và danh sách trang trí dài
- thật khó để cắt và dán danh sách trang trí để sử dụng lại, bởi vì nó bắt đầu và kết thúc ở giữa một dòng
Hình thức tiếp theo là cú pháp trang trí đi vào bên trong thân phương thức ngay từ đầu, ở cùng một vị trí mà các chuỗi tài liệu hiện đang hoạt động
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]0
Sự phản đối chính đối với biểu mẫu này là nó yêu cầu "nhìn trộm bên trong" thân phương thức để xác định các bộ trang trí. Ngoài ra, mặc dù mã nằm trong thân phương thức nhưng nó không được thực thi khi phương thức được chạy. Guido cảm thấy rằng chuỗi tài liệu không phải là một ví dụ phản biện tốt và rất có thể trình trang trí 'chuỗi tài liệu' có thể giúp di chuyển chuỗi tài liệu ra bên ngoài thân hàm
Hình thức cuối cùng là một khối mới bao quanh mã của phương thức. Đối với ví dụ này, chúng tôi sẽ sử dụng từ khóa 'trang trí', vì nó không hợp lý với @syntax
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]1
Hình thức này sẽ dẫn đến thụt đầu dòng không nhất quán cho các phương pháp trang trí và không trang trí. Ngoài ra, phần thân của phương thức được trang trí sẽ bắt đầu ba mức thụt lề trong
biểu mẫu cú pháp
@dec2 @dec1 def func[arg1, arg2, ...]: pass
4def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
6Các phản đối chính đối với cú pháp này là ký hiệu @ hiện không được sử dụng trong Python [và được sử dụng trong cả IPython và Leo] và ký hiệu @ không có ý nghĩa. Một phản đối khác là điều này "lãng phí" một ký tự hiện không được sử dụng [từ một bộ giới hạn] vào một thứ không được coi là mục đích sử dụng chính
@dec2 @dec1 def func[arg1, arg2, ...]: pass
5def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
3Đây là một biến thể của cú pháp @decorator – nó có ưu điểm là không phá vỡ IPython và Leo. Nhược điểm chính của nó so với @syntax là. biểu tượng trông giống cả chữ I viết hoa và chữ l viết thường
- cú pháp liệt kê
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
4Sự phản đối chính đối với cú pháp danh sách là nó hiện có nghĩa [khi được sử dụng ở dạng trước phương thức]. Nó cũng thiếu bất kỳ dấu hiệu nào cho thấy biểu thức là một trang trí
- cú pháp liệt kê sử dụng các dấu ngoặc khác [
@dec2 @dec1 def func[arg1, arg2, ...]: pass
6,@dec2 @dec1 def func[arg1, arg2, ...]: pass
7,…]def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
5None of these alternatives gained much traction. The alternatives which involve square brackets only serve to make it obvious that the decorator construct is not a list. They do nothing to make parsing any easier. The ‘’ alternative presents parsing problems because ‘’ already parse as un-paired. They present a further parsing ambiguity because a right angle bracket might be a greater than symbol instead of a closer for the decorators.
@dec2 @dec1 def func[arg1, arg2, ...]: pass
8Đề xuất của
@dec2 @dec1 def func[arg1, arg2, ...]: pass
8 là không có cú pháp mới nào được triển khai – thay vào đó là một chức năng kỳ diệu sử dụng nội quan để thao tác chức năng sau. Cả Jp Calderone và Philip Eby đều tạo ra các chức năng thực hiện điều này. Guido đã khá kiên quyết phản đối điều này – không có cú pháp mới, tính kỳ diệu của một chức năng như thế này là cực kỳ caoSử dụng các chức năng với “hành động từ xa” thông qua sys. settraceback có thể ổn đối với một tính năng tối nghĩa không thể có bất kỳ cách nào khác nhưng không đáng để thay đổi ngôn ngữ, nhưng đó không phải là tình huống dành cho người trang trí. Quan điểm phổ biến ở đây là các trình trang trí cần được thêm vào như một tính năng cú pháp để tránh các sự cố với ký hiệu hậu tố được sử dụng trong 2. 2 và 2. 3. Các công cụ trang trí dự kiến sẽ trở thành một tính năng ngôn ngữ mới quan trọng và thiết kế của chúng cần hướng tới tương lai, không bị hạn chế bởi những gì có thể triển khai trong 2. 3
- từ khóa mới [và chặn]
Ý tưởng này là sự thay thế đồng thuận từ comp. lang thang. python [thêm về điều này trong Đồng thuận cộng đồng bên dưới. ] Robert Brewer đã viết một tài liệu đề xuất J2 chi tiết phác thảo các lập luận ủng hộ biểu mẫu này. Các vấn đề ban đầu với hình thức này là
- Nó yêu cầu một từ khóa mới và do đó, một câu lệnh
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
00 - Việc lựa chọn từ khóa gây tranh cãi. Tuy nhiên,
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
01 nổi lên như một lựa chọn đồng thuận và được sử dụng trong đề xuất và triển khai - Dạng từ khóa/khối tạo ra thứ gì đó trông giống như một khối mã bình thường, nhưng không phải. Nỗ lực sử dụng các câu lệnh trong khối này sẽ gây ra lỗi cú pháp, có thể gây nhầm lẫn cho người dùng
Vài ngày sau, Guido từ chối đề xuất này với hai lý do chính, thứ nhất
… dạng cú pháp của một khối thụt vào gợi ý mạnh mẽ rằng nội dung của nó phải là một chuỗi các câu lệnh, nhưng thực tế không phải vậy – chỉ các biểu thức mới được phép và có một “sự thu thập” ngầm các biểu thức này cho đến khi chúng có thể được áp dụng . …
và thứ hai
… từ khóa bắt đầu dòng đứng đầu một khối thu hút rất nhiều sự chú ý đến nó. Điều này đúng với “if”, “while”, “for”, “try”, “def” và “class”. Nhưng từ khóa “sử dụng” [hoặc bất kỳ từ khóa nào khác ở vị trí của nó] không xứng đáng với sự chú ý đó; . …
Mời độc giả xem toàn văn phản hồi
- Nó yêu cầu một từ khóa mới và do đó, một câu lệnh
- Các chứng từ khác
Có rất nhiều biến thể và đề xuất khác trên trang wiki
Tại sao @?
Có một số lịch sử trong Java sử dụng @ ban đầu làm điểm đánh dấu trong các nhận xét Javadoc và sau đó trong Java 1. 5 cho các chú thích, tương tự như các trình trang trí Python. Thực tế là @ trước đây không được sử dụng làm mã thông báo trong Python cũng có nghĩa là rõ ràng là không có khả năng mã như vậy được phân tích cú pháp bởi phiên bản Python cũ hơn, dẫn đến các lỗi ngữ nghĩa có thể tinh vi. Điều đó cũng có nghĩa là sự mơ hồ về những gì là một trang trí và những gì không được loại bỏ. Điều đó nói rằng, @ vẫn là một lựa chọn khá độc đoán. Một số đã đề nghị sử dụng. thay thế
Đối với các tùy chọn cú pháp sử dụng cú pháp giống như danh sách [bất kể nó xuất hiện ở đâu] để chỉ định các trình trang trí, một vài lựa chọn thay thế đã được đề xuất.
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]02,
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]03 và
@dec2 @dec1 def func[arg1, arg2, ...]: pass6
Thực hiện hiện tại, Lịch sử
Guido đã yêu cầu một tình nguyện viên thực hiện cú pháp ưa thích của mình và Mark Russell đã bước lên và đăng một bản vá lên SF. Cú pháp mới này đã có sẵn trong 2. 4a2
@dec2 @dec1 def func[arg1, arg2, ...]: pass
Điều này tương đương với
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]0
mặc dù không có việc tạo biến trung gian có tên là
@dec2 @dec1 def func[arg1, arg2, ...]: pass0
Phiên bản được triển khai trong 2. 4a2 cho phép nhiều mệnh đề
@dec2 @dec1 def func[arg1, arg2, ...]: pass4 trên một dòng. Trong 2. 4a3, điều này đã được thắt chặt đến mức chỉ cho phép một người trang trí trên mỗi dòng
Một bản vá trước đó của Michael Hudson thực hiện cú pháp list-after-def cũng vẫn đang hoạt động
Sau 2. 4a2 đã được phát hành, trước phản ứng của cộng đồng, Guido tuyên bố rằng anh ấy sẽ kiểm tra lại đề xuất của cộng đồng, nếu cộng đồng có thể đưa ra sự đồng thuận của cộng đồng, một đề xuất phù hợp và triển khai. Sau một số lượng đáng kinh ngạc các bài đăng, thu thập một số lượng lớn các lựa chọn thay thế trong wiki Python, một sự đồng thuận của cộng đồng đã xuất hiện [bên dưới]. Guido sau đó đã từ chối mẫu thay thế này, nhưng đã thêm
Trong Python 2. 4a3 [sẽ được phát hành vào thứ Năm tuần này], mọi thứ vẫn như hiện tại trong CVS. Dành cho 2. 4b1, tôi sẽ xem xét thay đổi @ thành một ký tự đơn khác, mặc dù tôi nghĩ rằng @ có lợi thế là cùng một ký tự được sử dụng bởi một tính năng tương tự trong Java. Người ta lập luận rằng nó không hoàn toàn giống nhau, vì @ trong Java được sử dụng cho các thuộc tính không thay đổi ngữ nghĩa. Nhưng bản chất động của Python làm cho các yếu tố cú pháp của nó không bao giờ có ý nghĩa hoàn toàn giống như các cấu trúc tương tự trong các ngôn ngữ khác và chắc chắn có sự chồng chéo đáng kể. Về tác động đối với các công cụ của bên thứ 3. Tác giả của IPython không nghĩ rằng sẽ có nhiều tác động; . Tôi thực sự mong đợi rằng việc chọn một ký tự đã được sử dụng ở nơi khác trong cú pháp của Python có thể khó thích ứng hơn đối với các công cụ bên ngoài, vì việc phân tích cú pháp sẽ phải tinh tế hơn trong trường hợp đó. Nhưng tôi thực sự chưa quyết định, vì vậy có một số chỗ ngọ nguậy ở đây. Tôi không muốn xem xét các lựa chọn thay thế cú pháp khác vào thời điểm này. đồng tiền phải dừng lại ở một thời điểm nào đó, mọi người đều có tiếng nói của mình và chương trình phải tiếp tục
Đồng thuận cộng đồng
Phần này ghi lại cú pháp J2 bị từ chối và được đưa vào để hoàn thiện lịch sử
Sự đồng thuận nổi lên trên comp. lang thang. python là cú pháp J2 được đề xuất ["J2" là cách nó được tham chiếu trên trang wiki PythonDecorators]. từ khóa mới
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]01 đặt trước một khối trang trí trước câu lệnh
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]08. Ví dụ
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]8
Các đối số chính cho cú pháp này thuộc học thuyết "tính dễ đọc". Tóm lại, chúng là
- Một bộ tốt hơn nhiều @lines. Từ khóa và khối
def foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
01 chuyển đổi câu lệnhdef foo[cls]: pass foo = synchronized[lock][foo] foo = classmethod[foo]
08 khối đơn thành cấu trúc phức hợp nhiều khối, giống như thử/cuối cùng và các lệnh khác - Từ khóa tốt hơn dấu chấm câu cho mã thông báo mới. Một từ khóa phù hợp với việc sử dụng mã thông báo hiện có. Không cần loại mã thông báo mới. Một từ khóa phân biệt các trình trang trí Python với các chú thích Java và. Thuộc tính ròng, là những con thú khác nhau đáng kể
Robert Brewer đã viết một đề xuất chi tiết cho biểu mẫu này và Michael Sparks đã tạo ra một bản vá
Như đã lưu ý trước đây, Guido đã từ chối biểu mẫu này, nêu rõ các vấn đề của anh ấy với nó trong một thông báo tới python-dev và comp. lang thang. con trăn
ví dụ
Phần lớn cuộc thảo luận về
@classmethod @synchronized[lock] def foo[cls]: pass7 và danh sách gửi thư của
@classmethod @synchronized[lock] def foo[cls]: pass6 tập trung vào việc sử dụng các bộ trang trí như một cách rõ ràng hơn để sử dụng các nội trang
@classmethod @synchronized[lock] def foo[cls]: pass5 và
@classmethod @synchronized[lock] def foo[cls]: pass4. Khả năng này mạnh hơn nhiều so với khả năng đó. Phần này trình bày một số ví dụ về việc sử dụng