2012-10-13 31 views
8

Ngoài việc bỏ qua bất kỳ thuộc tính cá thể nào theo sở thích của tính chính xác, tra cứu phương pháp đặc biệt ngầm cũng thường bỏ qua phương thức __getattribute__() ngay cả đối tượng siêu di tích của đối tượng.Phương pháp đặc biệt nào bỏ qua __getattribute__ bằng Python?

The docs đề cập đến phương pháp đặc biệt như __hash__, __repr____len__, và tôi biết từ kinh nghiệm nó cũng bao gồm __iter__ cho Python 2.7.

Để báo an answer to a related question:

"Magic __methods__() được đối xử đặc biệt: Họ đang trong nội bộ giao cho 'khe' trong cấu trúc kiểu dữ liệu để tăng tốc độ của họ nhìn lên, và họ chỉ nhìn lên trong những khe. "

Để tìm cách cải thiện câu trả lời của tôi cho another question, tôi cần biết: Chúng tôi đang nói về phương pháp nào?

+0

Phương pháp nào được chỉ định cho các vị trí? –

+7

Tôi nghĩ mọi phương pháp được liệt kê [ở đây] (http://docs.python.org/reference/datamodel.html#specialnames). Dù sao đi nữa, điều này chỉ áp dụng nếu bạn gọi phương thức bằng cách sử dụng "cú pháp của nó". Ví dụ 'a + 5' sẽ không gọi' __getattribute__', trong khi 'a .__ add __ (5)' * sẽ * gọi nó. Về cơ bản '__getattribute__' được gọi bất cứ khi nào bạn sử dụng dấu chấm (' .') để truy cập thuộc tính. – Bakuriu

+0

@ Bakuriu: Rất nhiều thông tin, cảm ơn bạn. – porgarmingduod

Trả lời

4

Bạn có thể tìm câu trả lời trong python3 documentation cho object.__getattribute__, trong đó nêu:

gọi vô điều kiện để thực hiện thuộc tính truy cập cho trường hợp của lớp. Nếu lớp học cũng định nghĩa __getattr__(), thì sau đó sẽ không được gọi trừ khi __getattribute__() hoặc gọi số một cách rõ ràng hoặc tăng AttributeError. Phương thức này sẽ trả về giá trị thuộc tính (được tính) hoặc tăng ngoại lệ AttributeError. Trong để tránh đệ quy vô hạn trong phương pháp này, việc triển khai phải luôn gọi phương thức lớp cơ sở có cùng tên để truy cập bất kỳ thuộc tính nào cần, ví dụ, đối tượng. __getattribute__(self, name).

Note

Phương pháp này vẫn có thể được bỏ qua khi nhìn lên các phương pháp đặc biệt là kết quả của sự thỉnh nguyện ngầm qua cú pháp ngôn ngữ hoặc built-in chức năng. Xem tra cứu phương pháp đặc biệt.

cũng this trang giải thích chính xác cách "máy móc" này hoạt động. Về cơ bản, __getattribute__ chỉ được gọi khi bạn truy cập thuộc tính với toán tử . (dấu chấm) (và cũng bằng cách hasattr như Zagorulkin đã chỉ ra).

Lưu ý rằng trang không xác định những phương pháp đặc biệt được mặc nhiên ngẩng đầu lên, vì vậy tôi xét thấy tổ chức này cho tất cả trong số họ (mà bạn có thể tìm thấy here.

+0

bạn có thực sự kiểm tra không? tôi đã kiểm tra trên 2.7.9 và có vẻ như các tài liệu không hoàn toàn đúng về điều đó. –

1

Đã bắt đầu 2.7.9

couldn 't tìm cách nào để bỏ qua các cuộc gọi đến __getattribute__, với bất kỳ phương pháp huyền diệu được tìm thấy trên object hoặc type:

# Preparation step: did this from the console 
# magics = set(dir(object) + dir(type)) 
# got 38 names, for each of the names, wrote a.<that_name> to a file 
# Ended up with this: 

a.__module__ 
a.__base__ 
#... 

Đặt này ở sự bắt g của tập tin đó, mà tôi đổi tên thành một mô-đun python thích hợp (asdf.py)

global_counter = 0 

class Counter(object): 
    def __getattribute__(self, name): 
     # this will count how many times the method was called 
     global global_counter 
     global_counter += 1 
     return super(Counter, self).__getattribute__(name) 

a = Counter() 
# after this comes the list of 38 attribute accessess 
a.__module__ 
#... 
a.__repr__ 
#... 

print global_counter # you're not gonna like it... it printer 38 

Sau đó, tôi cũng đã cố gắng để có được mỗi người trong số những cái tên đó bởi getattrhasattr -> kết quả tương tự. __getattribute__ được gọi mỗi lần.

Vì vậy, nếu có ai có ý tưởng khác ... Tôi đã quá lười biếng để nhìn vào bên trong mã C cho điều này, nhưng tôi chắc chắn câu trả lời nằm ở đâu đó ở đó.

Vì vậy, hoặc có điều gì đó mà tôi không đúng hoặc tài liệu đang nói dối.

+1

Nếu tôi nhớ chính xác, câu hỏi của tôi là về 'repr (a)' trái ngược với 'a .__ repr __()'. Nó đã được một thời gian kể từ khi tôi đã vào công cụ này, nhưng tôi đoán bạn nhận được phiên bản getattribute bởi vì bạn tìm kiếm các thuộc tính, trong khi các phương pháp được xây dựng trong chúng tôi đang nói về (toàn cầu 'repr', không' __repr__') bỏ qua sự tồn tại của '__repr__'. – porgarmingduod

+0

Ghi đè '__getattribute__' để phát hành một bản in bất cứ khi nào nó được gọi và sau đó thực hiện:' Counter ('a') + Counter ('a') 'và thấy rằng nó không in bất cứ thứ gì. Bởi vì nó bỏ qua tên tiêu chuẩn tra cứu và nhấn 'Counter .__ dict __ ['__ add __']' trực tiếp hoặc một số điều ngớ ngẩn như vậy trong tên của tối ưu hóa. – justanr

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