2015-05-12 18 views
7

Mới đối với Python và đã thực hiện một số đọc, tôi đang thực hiện một số phương thức trong các phương thức lớp lớp tùy chỉnh của tôi chứ không phải là các phương thức mẫu.Python - tại sao tôi có thể gọi một phương thức lớp với một cá thể?

Vì vậy, tôi đã kiểm tra mã của tôi nhưng tôi đã không thay đổi một số phương pháp gọi để gọi phương thức trong lớp chứ không phải là trường hợp, nhưng họ vẫn làm việc:

class myclass: 
    @classmethod: 
    def foo(cls): 
     print 'Class method foo called with %s.'%(cls) 

    def bar(self): 
     print 'Instance method bar called with %s.'%(self) 

myclass.foo() 
thing = myClass() 
thing.foo() 
thing.bar() 

này tạo ra:

class method foo called with __main__.myclass. 
class method foo called with __main__.myclass. 
instance method bar called with <__main__.myclass instance at 0x389ba4>. 

Vì vậy, những gì tôi đang tự hỏi là tại sao tôi có thể gọi một phương thức lớp (foo) trên một thể hiện (thing.foo), (mặc dù nó là lớp được truyền cho phương thức)? Nó có ý nghĩa, vì 'thing' là 'myClass', nhưng tôi đã mong đợi Python đưa ra một lỗi nói điều gì đó dọc theo dòng 'foo là một phương thức lớp và không thể được gọi trên một cá thể'.

Đây có phải là kết quả mong đợi của thừa kế với đối tượng 'vật' kế thừa phương thức foo từ siêu lớp của nó không?

Nếu tôi cố gắng gọi phương thức dụ thông qua các lớp:

myclass.bar() 

sau đó tôi nhận được:

TypeError: unbound method bar() must be called with myclass instance... 

mà làm cho cảm giác hoàn hảo.

+0

Trong Python, các phương thức không được gọi là * on * gì đó. 'thing.foo' không phải là một lời gọi phương thức, nó là một truy cập thuộc tính, Về cơ bản nó giống với' getattr (điều, "foo") '. – Alexey

+0

@Alexey Chắc chắn 'foo' là một phương thức và 'thing.foo()' đang gọi phương thức 'foo' của đối tượng' điều'? Không phải là một thuộc tính của thuật ngữ Python cho những gì các ngôn ngữ khác gọi là một biến hoặc tài sản? –

+0

Tôi nghĩ rằng "' (thing.foo)() 'đang gọi phương thức' foo' của đối tượng 'điều'" (dấu ngoặc đơn cho sự rõ ràng) là một phép ẩn dụ cho "' (thing.foo)() 'đang gọi đối tượng có thể gọi 'thing.foo'", đó là nó. AFAIU, đối tượng này được tạo động khi 'getattr (điều," foo ")' được gọi, và dĩ nhiên nó có tham chiếu đến đối tượng 'thing'. – Alexey

Trả lời

6

Bạn có thể gọi nó trên một thể hiện vì @classmethod là một decorator (hàm này lấy hàm làm đối số và trả về hàm mới).

Dưới đây là một số thông tin relavent từ Python documentation

Nó có thể được gọi là một trong hai trên lớp (như Cf()) hoặc trên một thể hiện (chẳng hạn như C(). F()) . Ví dụ được bỏ qua ngoại trừ lớp của nó. Nếu một phương thức lớp học được gọi cho một lớp dẫn xuất, đối tượng lớp dẫn xuất được chuyển làm đối số đầu tiên ngụ ý.

Cũng có một thảo luận SO khá hay về @classmethodhere.

+0

Cảm ơn bạn - Tôi đã thực hiện các tìm kiếm khác nhau cho thừa kế, classmethods, vv, nhưng như bạn có thể tưởng tượng, kết quả đã được áp đảo. Tôi sẽ rất vui khi chỉ chấp nhận rằng nó hoạt động, nhưng với tư cách là một lập trình viên lắp ráp, tôi muốn biết mọi thứ hoạt động như thế nào dưới sự che chở. –

+0

"Bạn có thể gọi nó trên một thể hiện vì @classmethod là một trang trí" - tôi không làm theo logic này. – Alexey

+0

@Alexey bạn có biết người trang trí là gì không? – John

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