Siêu lực python __init__

Thực hiện đánh giá mã là một cách tuyệt vời để khám phá những điều mà mọi người có thể khó hiểu. Trong khi đọc bản sửa lỗi OpenStack gần đây, tôi phát hiện ra rằng mọi người không sử dụng đúng cách các trình trang trí khác nhau mà Python cung cấp cho các phương thức. Vì vậy, đây là nỗ lực của tôi trong việc cung cấp cho tôi một liên kết để gửi chúng đến trong các bài đánh giá mã tiếp theo của tôi. . -]

Cách các phương thức hoạt động trong Python

Một phương thức là một hàm được lưu trữ như một thuộc tính của lớp. Bạn có thể khai báo và truy cập một chức năng như vậy theo cách này

>>> class Pizza[object]:
..     def __init__[self, size]:
..         self.size = size
..     def get_size[self]:
..         return self.size
...
>>> Pizza.get_size

Điều Python nói với bạn ở đây là thuộc tính get_size của lớp Pizza là một phương thức không liên kết. Điều đó có nghĩa là gì?

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]

Chúng tôi không thể gọi nó vì nó không bị ràng buộc với bất kỳ phiên bản Pizza nào. Và một phương thức muốn một thể hiện làm đối số đầu tiên của nó [trong Python 2, nó phải là một thể hiện của lớp đó; trong Python 3, nó có thể là bất kỳ thứ gì]. Hãy cố gắng làm điều đó sau đó

>>> Pizza.get_size[Pizza[42]]
42

Nó đã làm việc. Chúng tôi đã gọi phương thức với một thể hiện là đối số đầu tiên của nó, vì vậy mọi thứ đều ổn. Nhưng bạn sẽ đồng ý với tôi nếu tôi nói rằng đây không phải là một cách thuận tiện để gọi các phương thức; . Và nếu chúng ta không biết lớp nào là đối tượng của mình, điều này sẽ không hoạt động lâu dài

Vì vậy, những gì Python làm cho chúng ta là nó liên kết tất cả các phương thức từ lớp

>>> Pizza.get_size[Pizza[42]]
42
0 với bất kỳ phiên bản nào của lớp này. Điều này có nghĩa là thuộc tính
>>> Pizza.get_size[Pizza[42]]
42
1 của một thể hiện của
>>> Pizza.get_size[Pizza[42]]
42
0 là một phương thức ràng buộc. một phương thức mà đối số đầu tiên sẽ là chính thể hiện

>>> Pizza[42].get_size

>>> Pizza[42].get_size[]
42

Theo dự kiến, chúng tôi không phải cung cấp bất kỳ đối số nào cho

>>> Pizza.get_size[Pizza[42]]
42
1, vì nó bị ràng buộc, đối số
>>> Pizza.get_size[Pizza[42]]
42
4 của nó sẽ tự động được đặt thành phiên bản
>>> Pizza.get_size[Pizza[42]]
42
0 của chúng tôi. Đây là một bằng chứng tốt hơn về điều đó

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
0

Thật vậy, bạn thậm chí không cần phải giữ một tham chiếu đến đối tượng

>>> Pizza.get_size[Pizza[42]]
42
0 của mình. Phương thức của nó được liên kết với đối tượng, vì vậy phương thức là đủ cho chính nó

Nhưng nếu bạn muốn biết phương thức ràng buộc này được liên kết với đối tượng nào thì sao?

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
2

Rõ ràng, chúng ta vẫn có một tham chiếu đến đối tượng của mình và chúng ta có thể tìm lại nó nếu muốn

Trong Python 3, các hàm được gắn với một lớp không được coi là phương thức không liên kết nữa mà là các hàm đơn giản, được liên kết với một đối tượng nếu được yêu cầu. Vì vậy, nguyên tắc vẫn giữ nguyên, mô hình chỉ được đơn giản hóa

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
3Phương thức tĩnh

Các phương thức tĩnh là một trường hợp đặc biệt của các phương thức. Đôi khi, bạn sẽ viết mã thuộc về một lớp, nhưng điều đó hoàn toàn không sử dụng đối tượng đó. Ví dụ

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
4

Trong trường hợp như vậy, viết

>>> Pizza.get_size[Pizza[42]]
42
7 như một phương thức không tĩnh cũng sẽ hoạt động, nhưng nó sẽ cung cấp cho nó một đối số
>>> Pizza.get_size[Pizza[42]]
42
4 sẽ không được sử dụng. Đây, người trang trí
>>> Pizza.get_size[Pizza[42]]
42
9 mua cho chúng tôi vài thứ

  • Python không phải khởi tạo một phương thức ràng buộc cho mỗi đối tượng
    >>> Pizza.get_size[Pizza[42]]
    42
    
    0 mà chúng ta khởi tạo. Các phương thức ràng buộc cũng là các đối tượng và việc tạo chúng có chi phí. Có một phương pháp tĩnh tránh điều đó
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
9
  • Nó làm giảm khả năng đọc của mã. nhìn thấy

    >>> Pizza.get_size[Pizza[42]]
    42
    
    9, chúng ta biết rằng phương thức không phụ thuộc vào trạng thái của chính đối tượng;

  • Nó cho phép chúng ta ghi đè phương thức

    >>> Pizza.get_size[Pizza[42]]
    42
    
    7 trong một lớp con. Nếu chúng ta sử dụng một hàm
    >>> Pizza.get_size[Pizza[42]]
    42
    
    7 được xác định ở cấp cao nhất của mô-đun, thì một lớp kế thừa từ
    >>> Pizza.get_size[Pizza[42]]
    42
    
    0 sẽ không thể thay đổi cách chúng ta trộn nguyên liệu cho bánh pizza mà không ghi đè chính
    >>> Pizza[42].get_size
    
    >>> Pizza[42].get_size[]
    42
    
    5

phương pháp lớp

Như đã nói, phương thức của lớp là gì? .
not bound to an object, but to… a class!

>>> Pizza.get_size[Pizza[42]]
42
5

Dù bạn sử dụng cách nào để truy cập phương thức này, nó sẽ luôn được liên kết với lớp mà nó được gắn vào và đối số đầu tiên của nó sẽ là chính lớp đó [hãy nhớ rằng các lớp cũng là đối tượng]

Khi nào sử dụng loại phương pháp này?

  • Các phương thức xuất xưởng, được sử dụng để tạo một thể hiện cho một lớp bằng cách sử dụng một số loại tiền xử lý chẳng hạn. Thay vào đó, nếu chúng tôi sử dụng
    >>> Pizza.get_size[Pizza[42]]
    42
    
    9, chúng tôi sẽ phải mã hóa cứng tên lớp
    >>> Pizza.get_size[Pizza[42]]
    42
    
    0 trong hàm của mình, khiến bất kỳ lớp nào kế thừa từ
    >>> Pizza.get_size[Pizza[42]]
    42
    
    0 không thể sử dụng nhà máy của chúng tôi cho mục đích sử dụng riêng
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
0
  • Các phương thức tĩnh gọi các phương thức tĩnh. nếu bạn chia một phương thức tĩnh thành nhiều phương thức tĩnh, bạn không nên mã hóa tên lớp mà hãy sử dụng các phương thức lớp. Sử dụng cách này để khai báo phương thức của chúng ta, tên
    >>> Pizza.get_size[Pizza[42]]
    42
    
    0 không bao giờ được tham chiếu trực tiếp và việc kế thừa và ghi đè phương thức sẽ hoạt động hoàn hảo
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
1Phương pháp trừu tượng

Phương thức trừu tượng là phương thức được định nghĩa trong lớp cơ sở nhưng có thể không cung cấp bất kỳ triển khai nào. Trong Java, nó sẽ mô tả các phương thức của một giao diện

Vì vậy, cách đơn giản nhất để viết một phương thức trừu tượng trong Python là

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
2

Bất kỳ lớp nào kế thừa từ

>>> Pizza.get_size[Pizza[42]]
42
0 nên triển khai và ghi đè phương thức
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
01, nếu không sẽ xảy ra ngoại lệ

Cách cụ thể này để thực hiện phương pháp trừu tượng có một nhược điểm. Nếu bạn viết một lớp kế thừa từ

>>> Pizza.get_size[Pizza[42]]
42
0 và quên triển khai
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
01, lỗi sẽ chỉ xuất hiện khi bạn thử sử dụng phương pháp đó

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
3

Có một cách để kích hoạt theo cách này sớm hơn, khi đối tượng đang được khởi tạo, sử dụng mô-đun abc được cung cấp cùng với Python

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
4

Sử dụng

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
04 và lớp đặc biệt của nó, ngay khi bạn cố gắng khởi tạo
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
05 hoặc bất kỳ lớp nào kế thừa từ nó, bạn sẽ nhận được một
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
06

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
5Kết hợp các phương thức tĩnh, lớp và trừu tượng

Khi xây dựng các lớp và thừa kế, sẽ đến lúc bạn phải kết hợp tất cả các phương thức trang trí này. Vì vậy, đây là một số lời khuyên về nó

Hãy nhớ rằng việc khai báo một phương thức là trừu tượng, không đóng băng nguyên mẫu của phương thức đó. Điều đó có nghĩa là nó phải được triển khai, nhưng nó có thể được triển khai với bất kỳ danh sách đối số nào

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
6

Điều này hợp lệ, vì

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
07 đáp ứng yêu cầu giao diện mà chúng tôi đã xác định cho các đối tượng
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
05. Điều đó có nghĩa là chúng ta cũng có thể triển khai nó như một lớp hoặc một phương thức tĩnh chẳng hạn

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
7

Điều này cũng đúng và đáp ứng hợp đồng mà chúng tôi có với lớp trừu tượng

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
05 của chúng tôi. Việc phương thức
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
20 không cần biết về đối tượng để trả về kết quả là một chi tiết triển khai, không phải là tiêu chí để hoàn thành hợp đồng của chúng tôi

Do đó, bạn không thể buộc việc triển khai phương thức trừu tượng của mình thành phương thức thông thường, lớp hoặc tĩnh và có thể nói là bạn không nên. Bắt đầu với Python 3 [điều này sẽ không hoạt động như bạn mong đợi trong Python 2, xem vấn đề5867], giờ đây có thể sử dụng các trình trang trí

>>> Pizza.get_size[Pizza[42]]
42
9 và
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
22 trên đầu trang của
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
23

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
8

Đừng hiểu lầm điều này. nếu bạn nghĩ rằng điều này sẽ buộc các lớp con của bạn triển khai

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
20 như một phương thức của lớp thì bạn đã nhầm. Điều này chỉ ngụ ý rằng việc bạn triển khai
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
20 trong lớp
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
05 là một phương thức lớp

Một triển khai trong một phương pháp trừu tượng? . Trong Python, trái ngược với các phương thức trong giao diện Java, bạn có thể có mã trong các phương thức trừu tượng của mình và gọi nó qua

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
27

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
9

Trong trường hợp như vậy, mọi chiếc bánh pizza bạn sẽ tạo bằng cách kế thừa từ

>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
05 sẽ phải ghi đè phương thức
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
20, nhưng sẽ có thể sử dụng cơ chế mặc định để lấy danh sách thành phần bằng cách sử dụng
>>> Pizza.get_size[]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unbound method get_size[] must be called with Pizza instance as first argument [got nothing instead]
27

Nếu bạn muốn biết thêm, tôi đã đề cập nhiều đến chủ đề này trong Hướng dẫn về Python của Hacker. Kiểm tra nó ra

Chủ Đề