Trình trang trí cho phương thức lớp python

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]:
    pass
4 và
@classmethod
@synchronized[lock]
def foo[cls]:
    pass
5] đã 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]:
    pass
6 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]:
    pass
7 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, ...]:
    pass
0. 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, ...]:
    pass
1 dịch thành
@dec2
@dec1
def func[arg1, arg2, ...]:
    pass
2

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, ...]:
    pass
3 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
    
    4

    def foo[cls]:
        pass
    foo = synchronized[lock][foo]
    foo = classmethod[foo]
    
    6

    Cá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
    
    5

    def 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]
    
    4

    Sự 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]
    
    5

    None 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ỳ cao

    Sử 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

  • 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, ...]:
    pass
6

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, ...]:
    pass
0

Phiên bản được triển khai trong 2. 4a2 cho phép nhiều mệnh đề

@dec2
@dec1
def func[arg1, arg2, ...]:
    pass
4 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ệnh
    def 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]:
    pass
7 và danh sách gửi thư của
@classmethod
@synchronized[lock]
def foo[cls]:
    pass
6 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]:
    pass
5 và
@classmethod
@synchronized[lock]
def foo[cls]:
    pass
4. 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

Chúng ta có thể sử dụng trình trang trí trên lớp trong Python không?

Trong Python, bộ trang trí có thể là hàm hoặc lớp . Trong cả hai trường hợp, trang trí thêm chức năng cho các chức năng hiện có. Khi chúng ta trang trí một hàm với một lớp, thì hàm đó sẽ trở thành một thể hiện của lớp.

Trang trí có thể được sử dụng trong lớp học?

Chúng ta có thể dễ dàng tạo các công cụ trang trí bên trong một lớp và nó có thể dễ dàng truy cập đối với các lớp con của nó.

Phương thức @class trong Python là gì?

Phương thức của lớp là phương thức được liên kết với lớp chứ không phải đối tượng của lớp . Họ có quyền truy cập vào trạng thái của lớp vì nó nhận tham số lớp trỏ đến lớp chứ không phải thể hiện đối tượng. Nó có thể sửa đổi trạng thái lớp sẽ áp dụng trên tất cả các phiên bản của lớp.

Hàm trang trí nào sau đây được sử dụng để tạo một phương thức lớp trong Python?

Các trình trang trí @classmethod và @staticmethod được sử dụng để xác định các phương thức bên trong một không gian tên lớp không được kết nối với một thể hiện cụ thể của lớp đó

Chủ Đề