2012-06-15 51 views
19

Ok vì vậy tôi có mã này:'classmethod' đối tượng không phải là callable

class SomeClass: 
    @classmethod 
    def func1(cls,arg1): 
     #---Do Something--- 
    @classmethod 
    def func2(cls,arg1): 
     #---Do Something--- 

    # A 'function map' that has function name as its keys and the above function 
    # objects as values 
    func_map={'func1':func1,'func2':func2} 

    @classmethod 
    def func3(cls,arg1): 
     # following is a dict(created by reading a config file) that 
     # contains func names as keys and boolean as values that tells 
     # the program whether or not to run that function 
     global funcList 
     for func in funcList: 
      if funcList[func]==True: 
       cls.func_map[func](arg1)  #TROUBLING PART!!! 

    if _name__='main' 
     SomeClass.func3('Argumentus-Primus') 

Khi tôi chạy này, tôi tiếp tục nhận được lỗi:

 
Exception TypeError: "'classmethod' object is not callable" 

Tôi không thể tìm ra whats sai với điều này và sẽ đánh giá cao sự giúp đỡ của bạn.

+0

Xin lỗi vì không thêm mô tả lỗi. Đã chỉnh sửa câu trả lời (và đó là tất cả những gì tôi biết về lỗi này). Và nếu tôi có câu trả lời cho vấn đề tại sao tôi thậm chí sẽ đăng câu hỏi này? : S Tôi đã xem xét lỗi này và thấy rằng mọi người gặp phải các lỗi này vì họ không sử dụng mã chính xác, ví dụ: trên một chủ đề một chàng trai đang truy cập vào một phần tử của một từ điển như 'someDict (key)' và đã nhận được lỗi tương tự .. nhưng tôi tin rằng tôi đang thực hiện một cuộc gọi đến một hàm (nên được gọi, đúng không?). Sửa lỗi nếu tôi sai .. – user1126425

+0

Khi bạn gặp lỗi, hãy sao chép dán toàn bộ dấu vết ngăn xếp. Nó sẽ cho bạn biết những điều hữu ích như những gì dòng lỗi xảy ra trên. –

+0

Lattye, 'Loại ngoại lệError:" đối tượng 'classmethod' không thể gọi được "trong 'pyadecg.__wrap_py_func 'ignore' đây là tất cả những gì tôi có thể thấy trong stacktrace .. Cảm ơn sự giúp đỡ của bạn – user1126425

Trả lời

12

Bạn không thể tạo tài liệu tham khảo để classmethods cho đến khi lớp học đã được xác định. Bạn sẽ phải di chuyển nó ra khỏi định nghĩa lớp. Tuy nhiên bằng cách sử dụng một bản đồ chức năng toàn cầu để quyết định những gì được chạy thực sự là vụng về. Nếu bạn mô tả những gì bạn đang cố gắng làm với điều này, chúng tôi có lẽ có thể đề xuất một giải pháp tốt hơn.

class SomeClass(object): 
    @classmethod 
    def func1(cls, arg1): 
     print("Called func1({})".format(arg1)) 

    @classmethod 
    def func2(cls, arg1): 
     print("Call func2({})".format(arg1)) 

    @classmethod 
    def func3(cls, arg1): 
     for fnName,do in funcList.iteritems(): 
      if do: 
       try: 
        cls.func_map[fnName](arg1) 
       except KeyError: 
        print("Don't know function '{}'".format(fnName)) 

# can't create function map until class has been created 
SomeClass.func_map = { 
    'func1': SomeClass.func1, 
    'func2': SomeClass.func2 
} 

if __name__=='__main__': 
    funcList = {'func1':True, 'func2':False} 
    SomeClass.func3('Argumentus-Primus') 
+2

Cảm ơn câu trả lời Hugh. 1. Điều này thực sự gây nhầm lẫn cho tôi. Tại sao không python dừng lại ngay tại chỗ đó khi tôi đã chỉnh sửa chúng trong dict? Nó chỉ phàn nàn khi tôi cố gắng gọi nó. 2. Danh sách funcList toàn cầu này được tạo bằng cách đọc tệp cấu hình (đọc cấu hình đang được thực hiện trong một mô-đun khác), vì vậy tôi không thể nghĩ ra cách khác ... 3. Tôi đang cố gắng lấy cấu hình đầu vào tập tin từ người dùng sẽ cho chương trình biết chức năng nào để chạy và trong khi làm như vậy muốn duy trì sự tách biệt rõ ràng giữa các phần mã khác nhau (để dễ mở rộng) – user1126425

0

Thêm tự làm đối số cho mỗi phương thức trong lớp học.

Cũng

if _name__='main' 
    SomeClass.func3('Argumentus-Primus') 

sẽ trông như thế này:

if __name__=='__main__': 
    SomeClass.func3('Argumentus-Primus') 

và không nên trong cơ thể của lớp.

+0

đây là tất cả các phương pháp lớp không phải là các phương thức ví dụ. – user1126425

+0

Tôi hiểu. Tại sao bạn không chỉ sử dụng câu lệnh switch thay vì bản đồ? Hoặc bạn có thể sử dụng getattr để gọi phương thức. Đó là nếu bạn đã làm cho nó một phương pháp dụ. – ulu5

+0

Đã cố gắng để được thanh lịch trong mã của tôi ... và viết nó để nó có thể dễ dàng mở rộng :) Tôi không muốn sử dụng nó như là phương pháp dụ ... bởi vì nó làm thay đổi một số tài nguyên được sử dụng bởi các mô-đun khác cần xem chúng theo cách nhất quán .. – user1126425

2

Một lớp học kết thúc tốt đẹp một hàm nhất định với một đối tượng ma thuật không thực sự có thể gọi được. Nó chỉ có thể được gọi bằng cách sử dụng cú pháp ClassName.method(args).

tôi sẽ không khuyên bạn nên làm theo cách này, hãy xem xét làm một cái gì đó giống như thay vì điều này:

func_list = { 
    'func1': True, 
    'func2': False 
} 

class SomeClass(object): 
    def do_func1(self, arg1): 
     print("func1", arg1) 

    def do_func2(self, arg1): 
     print("func2", arg1) 

    def run(self, arg1): 
     for name, enabled in func_list.items(): 
      if enabled: 
       the_method = getattr(self, 'do_' + name) 
       the_method(arg1) 


if __name__ == '__main__': 
    sc = SomeClass() 
    sc.run('Argumentus-Primus') 
+0

Cảm ơn bạn đã trả lời Antti. Bạn có nói rằng một phương thức lớp không thể gọi được? Trong trường hợp của tôi, tôi có thể gọi hàm func3 bằng cách sử dụng SomeClass.func3 (arg1), nhưng vấn đề dường như đang gọi với các hàm khác. Ngoài ra, tôi cần classmethods để tôi có thể làm mà không instantiating lớp này trong các mô-đun khác (đó là loại một hạn chế của mã của tôi). – user1126425

+0

Và tại sao không khởi tạo? Nếu bạn không bao giờ khởi tạo lớp, bạn không cần một lớp học. Thậm chí không phải lớp học ... –

+0

Hmm .. Tôi nghĩ bạn đúng. Tôi đã theo các quy ước Java .. Dù sao nó đã giới thiệu tôi với vấn đề này và tôi muốn tìm hiểu tại sao tôi không thể làm theo cách này? – user1126425

0

Bạn có thể cần thử phương pháp tĩnh.

@staticmethod 
def function():... 

Phương pháp tĩnh không vượt qua lớp dưới dạng đối số ngầm định.

+1

Thú vị, nhưng nó chỉ dẫn đến 'TypeError: 'staticmethod' thay vào đó, đối tượng không thể gọi được. – starfry

9

tôi phát hiện ra một cái gì đó tối nay rằng sẽ rất hữu ích ở đây: Chúng ta có thể unwrap diệu staticmethodclassmethod đối tượng thông qua: getattr(func, '__func__')

Làm sao tôi tìm thấy thông tin này? Sử dụng PyCharm của JetBrains (Tôi không biết về các IDE Python khác), tôi đã xem mã nguồn cho @staticmethod@classmethod. Cả hai lớp đều xác định thuộc tính __func__.

"Phần còn lại được để làm bài tập cho người đọc".

+2

Đó chỉ là sơ khai tạo ra cho pycharm để hoàn thành mã và làm việc nội tâm. Trong thực tế, những người trang trí là nội trang được viết bằng C –

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