2013-04-19 26 views
7

Gần đây tôi đọc các official HOW-TO about Python descriptors, mà thực sự xuất phát từ an essay được viết bởi Raymond Hettinger từ lâu. Nhưng sau khi đọc nó nhiều lần, tôi vẫn còn bối rối về một số phần của nó. Tôi sẽ trích dẫn một số đoạn văn, tiếp theo là sự nhầm lẫn và câu hỏi của tôi.Mâu thuẫn về Python Descriptor và <Descriptor HowTo Guide>


Nếu từ điển của một ví dụ có một mục có cùng tên như một mô tả dữ liệu, mô tả dữ liệu được ưu tiên. Nếu từ điển của một cá thể có một mục có cùng tên với bộ mô tả phi dữ liệu, mục nhập từ điển sẽ được ưu tiên.

  • Điều này có giống với lớp học không? Chuỗi ưu tiên của một lớp là gì nếu từ điển của nó có một mục có cùng tên với bộ mô tả dữ liệu/phi dữ liệu?

Đối với các đối tượng, các máy móc thiết bị là trong object.__getattribute__() mà biến b.x vào type(b).__dict__['x'].__get__(b, type(b)). Việc triển khai hoạt động thông qua một chuỗi ưu tiên cung cấp ưu tiên dữ liệu mô tả trên các biến mẫu, các biến mẫu ưu tiên trên các bộ mô tả phi dữ liệu và gán mức ưu tiên thấp nhất cho __getattr__() nếu được cung cấp.

Đối với các lớp học, máy móc ở số type.__getattribute__() biến đổi B.x thành B.__dict__['x'].__get__(None, B).

  • Hai đoạn trên cho biết quá trình mô tả được gọi tự động khi truy cập thuộc tính. Nó liệt kê sự khác biệt giữa thuộc tính đang được truy cập bởi một cá thể (b.x) và một lớp (B.x). Tuy nhiên, đây là nhầm lẫn của tôi:
    • nếu các thuộc tính của một lớp hoặc một thể hiện không phải là một mô tả, sẽ chuyển đổi (ví dụ, biến đổi b.x vào type(b).__dict__['x'].__get__(b, type(b))B.x vào B.__dict__['x'].__get__(None, B)) vẫn tiếp tục? Trả lại thuộc tính trong lớp học hoặc ví dụ dict trực tiếp đơn giản hơn?
    • Nếu từ điển của một thể hiện có mục nhập có cùng tên với bộ mô tả phi dữ liệu, theo quy tắc ưu tiên trong báo giá đầu tiên, mục nhập từ điển sẽ được ưu tiên, tại thời điểm này chuyển đổi vẫn tiếp tục? Hoặc chỉ trả lại giá trị trong số dict của mình?

mô tả Non-dữ liệu cung cấp một cơ chế đơn giản cho các biến thể trên các mô hình thông thường của ràng buộc chức năng vào phương pháp.

  • Được mô tả phi dữ liệu được lựa chọn bởi vì chức năng/phương pháp chỉ có thể được nhận, nhưng không thể thiết?
  • Cơ chế cơ bản cho các hàm ràng buộc thành các phương thức là gì?Vì các từ điển lớp lưu trữ các phương thức như các hàm, nếu chúng ta gọi cùng một phương thức bằng cách sử dụng một lớp và cá thể của nó tương ứng, làm thế nào hàm có thể cho biết đối số đầu tiên của nó có phải là tự hay không?

Chức năng có một phương pháp __get__() để họ có thể được chuyển đổi sang một phương pháp khi truy cập như là thuộc tính. Trình mô tả phi dữ liệu chuyển đổi một cuộc gọi obj.f(*args) thành f(obj, *args). Gọi klass.f(*args) trở thành f (* args).

  • Làm thế nào một bộ mô tả phi dữ liệu có thể chuyển đổi một cuộc gọi obj.f(*args) vào f(obj, *args)?
  • Làm cách nào để mô tả phi dữ liệu biến đổi một cuộc gọi klass.f(*args) thành f(*args)?
  • Cơ chế cơ bản của hai phép biến đổi trên là gì? Tại sao sự khác biệt tồn tại giữa lớp và cá thể?
  • Vai trò của phương pháp __get__() trong trường hợp trên là gì?

Trả lời

2

Điều này có giống với lớp học không? Chuỗi ưu tiên của một lớp là gì nếu từ điển của nó có một mục có cùng tên với bộ mô tả dữ liệu/phi dữ liệu?

Không, nếu thuộc tính được xác định cả trong lớp cha và lớp con, giá trị siêu lớp được bỏ qua hoàn toàn.

nếu các thuộc tính của một lớp hoặc một thể hiện không phải là một mô tả, sẽ chuyển đổi (ví dụ, biến đổi BX vào type(b).__dict__['x'].__get__(b, type(b)) và Bx vào B.__dict__['x'].__get__(None, B)) vẫn tiếp tục?

Không, nó sẽ trả trực tiếp đối tượng nhận được từ lớp của __dict__. Hoặc tương đương, vâng, nếu bạn giả vờ rằng tất cả các đối tượng có theo mặc định một phương pháp __get__() mà bỏ qua đối số của nó và trả về self.

Nếu từ điển của một cá thể có một mục có cùng tên với bộ mô tả phi dữ liệu, theo quy tắc ưu tiên trong báo giá đầu tiên, mục nhập từ điển sẽ được ưu tiên, tại thời điểm này chuyển đổi vẫn tiếp tục? Hoặc chỉ trả lại giá trị trong dict của nó?

gì chưa rõ trong đoạn mà bạn trích dẫn (có thể nó được viết xuống những nơi khác) là khi b.x quyết định trở về b.__dict__['x'], không __get__ được gọi trong mọi trường hợp. __get__ được gọi chính xác khi cú pháp b.x hoặc B.x quyết định trả lại đối tượng sống trong một số lớp dict.

Mô tả không phải dữ liệu được chọn vì các hàm/phương thức chỉ có thể nhận được, nhưng không thể được đặt?

Có: họ là một sự tổng quát của "kiểu cũ" mô hình lớp trong Python, trong đó bạn có thể nói B.f = 42 ngay cả khi f là một đối tượng chức năng sống trong lớp B. Điều này cho phép các đối tượng chức năng được overriden với một vật không liên quan. Mặt khác, các bộ mô tả dữ liệu có một logic khác nhau để hỗ trợ property.

Cơ chế cơ bản cho các chức năng liên kết thành phương pháp là gì? Vì các từ điển lớp lưu trữ các phương thức như các hàm, nếu chúng ta gọi cùng một phương thức bằng cách sử dụng một lớp và cá thể của nó tương ứng, làm sao hàm có thể cho biết đối số đầu tiên của nó có phải là tự hay không?

Để hiểu điều này, bạn cần phải có "đối tượng phương pháp". Cú pháp b.f(*args) tương đương với (b.f)(*args), là hai bước. Bước đầu tiên gọi f.__get__(b); điều này trả về một đối tượng phương thức lưu trữ cả b và f. Bước thứ hai gọi đối tượng phương thức, nó sẽ lần lượt gọi hàm f ban đầu bằng cách thêm b làm đối số thừa. Đây là điều không xảy ra cho B.f, chỉ đơn giản là vì B.f, tức là f.__get__(None, B), chỉ là f (trong Python 3). Đó là cách mà phương pháp đặc biệt __get__ được thiết kế trên các đối tượng chức năng.

Các vấn đề liên quan