Tôi thích xem hành vi này từ "từ dưới lên".
Hàm trong Python hoạt động như "descriptor object". Như vậy, nó có phương thức __get__()
.
Quyền truy cập đọc vào thuộc tính lớp có phương thức __get__()
được chuyển hướng đến phương thức này. Quyền truy cập thuộc tính vào lớp được thực hiện dưới dạng attribute.__get__(None, containing_class)
, trong khi quyền truy cập thuộc tính đối với cá thể được ánh xạ tới attribute.__get__(instance, containing_class)
.
Nhiệm vụ của phương thức __get__()
của hàm là bao bọc hàm trong đối tượng phương thức bao bọc thông số self
- đối với trường hợp truy cập thuộc tính đối tượng. Điều này được gọi là một phương pháp ràng buộc.
Trên truy cập thuộc tính lớp trên 2.x, hàm __get__()
của hàm trả về trình bao bọc phương thức không gắn kết, trong khi, như tôi learned today, trên 3.x, nó tự trả về. (Lưu ý rằng cơ chế __get__()
vẫn tồn tại trong 3.x, nhưng một hàm chỉ trả về chính nó.) Đó là gần như giống nhau, nếu bạn nhìn vào cách nó được gọi, nhưng một wrapper phương pháp unbound bổ sung kiểm tra cho các loại chính xác của đối số self
.
Cuộc gọi staticmethod()
chỉ tạo đối tượng có lệnh gọi __get__()
được thiết kế để trả lại đối tượng ban đầu đã cho để nó hoàn tác hành vi được mô tả. Đó là cách HYRY's trick hoạt động: thuộc tính acces undoes gói staticmethod()
, cuộc gọi lại thực hiện để thuộc tính "mới" có cùng trạng thái như cũ, mặc dù trong trường hợp này, staticmethod()
dường như được áp dụng hai lần (nhưng thực sự isn ' t).
(BTW: Nó còn hoạt động trong bối cảnh kỳ lạ này:.
s = staticmethod(8)
t = s.__get__(None, 2) # gives 8
mặc dù 8
không phải là một chức năng và 2
không phải là một lớp)
Trong câu hỏi của bạn, bạn có hai tình huống:
cmd = Cmd.cmdOne
cmd() # works fine
truy cập lớp học và yêu cầu thuộc tính cmdOne
, đối tượng staticmethod()
. Điều này được truy vấn thông qua __get__()
của nó và trả về hàm ban đầu, sau đó được gọi. Đó là lý do tại sao nó hoạt động tốt.
Cmd.cmd = Cmd.cmdOne
Cmd.cmd() # unbound error
làm tương tự, nhưng sau đó gán chức năng này cho Cmd.cmd
. Dòng tiếp theo là một truy cập thuộc tính - một lần nữa, cuộc gọi __get__()
đến chính hàm đó và do đó trả về một phương thức không liên kết, phải được gọi với đối tượng self
chính xác làm đối số đầu tiên.
Không trả lời câu hỏi. – martineau