2012-03-15 59 views
40

Đối với một số lý do, phương pháp super() không phải luôn luôn hành xử như mong đợi, chọn quay trở lại:Python siêu() hành vi không đáng tin cậy

TypeError('super(type, obj): obj must be an instance or subtype of type)' 

tôi hiểu những gì lỗi nghĩa. Tôi không hiểu tại sao nó lại xuất hiện như một lỗi. Đây là đoạn mã đang phá vỡ. Tất cả các đối tượng trong hệ thống là các đối tượng kiểu mới.

Điều thực sự thú vị là lỗi này không luôn hiển thị. Tôi không biết điều gì gây ra nó. Phương pháp super() trong Retrieval đang chuyển qua lớp Retrieval và sau đó là đối tượng, theo như tôi biết, chính xác cách super()được yêu cầu để được gọi.

Bạn nghĩ gì?

Trong file DBConnection.py:

class DBAdminConnection(object): 
    def __init__(self): 
     self.user = DBUserConnection().user 
     self.submissions = DBSubmissionConnection() 

Trong file Retrieval.py

class Retrieval(DBConnection.DBAdminConnection): 
    def __init__(self, username=None, password=None, unique_key=None): 
     super(Retrieval,self).__init__() 
     if username and password: 
      self.username = username 
      self.user.login(username,password, config.DATABASE) 
      if self.user.error: 
       raise UserLoginError(username) 
     self.unique_key = unique_key 

Trả lời

57

Bạn tải lại các module bằng cách nào đó ở giữa của sự vật? Nếu có, điều đó có thể giải thích lỗi này.

isinstance(self,DBAdminConnection) có thể trở thành sai sau khi tải lại mô-đun vì các thay đổi đối với tham chiếu bộ nhớ.

Edit: nếu bạn đang chạy ứng dụng web.py của bạn dưới mod_wsgi, chắc chắn bạn sẽ vô hiệu hóa tự động nạp lại:

app = web.application(urls, globals(), autoreload=False) 
+0

Điều này đang chạy qua webpy. Cho nên đó là khả năng nhất định. Đặc biệt là kể từ khi tôi giết các ứng dụng dụ và respawn nó, vấn đề biến mất. Wow. Bây giờ câu hỏi trở nên như thế nào để sửa chữa nó. –

+0

@TomThorogood: bạn đang chạy ứng dụng của mình như thế nào? Bạn đang sử dụng mod_wsgi? –

+0

@TomThorogood: đã thêm điều gì đó trong trường hợp bạn đang sử dụng wsgi. –

1

Tôi không chắc chắn lý do tại sao các lỗi đang xảy ra, nhưng như một trợ giúp để gỡ lỗi, bạn có thể kết thúc cuộc gọi đến super trong khối try/except và thực hiện kết xuất dữ liệu khi ngoại lệ được nâng lên. Một cái gì đó như thế này:

class Retrieval(DBConnection.DBAdminConnection): 
    def __init__(self, username=None, password=None, unique_key=None): 
     try: 
      super(Retrieval,self).__init__() 
     except TypeError, e: 
      print "Failure initialising Retrieval --> self: %r" 
      raise 
     if username and password: 
      self.username = username 
      self.user.login(username,password, config.DATABASE) 
      if self.user.error: 
       raise UserLoginError(username) 
     self.unique_key = unique_key 
+0

Bạn có nghĩa là bạn không chắc chắn? Bởi vì bạn có hy vọng của tôi trong một thời điểm./grin –

+0

@TomThorogood: Ack! Ừ, ý tôi là 'không chắc' - xin lỗi! –

+0

haha. đừng lo lắng! Cảm ơn vì điều này. Tôi có một số gỡ lỗi tại chỗ; tôi chỉ đang dọn dẹp mã cho SO. –

11

Nếu bạn đang sử dụng tải lại() như một phần của công việc của bạn, bạn rõ ràng cũng cần phải sử dụng super(self.__class__, self).__init__ cho thừa kế khởi tạo.

Tôi nghi ngờ bạn sẽ tìm thấy lỗi này trùng với id(self.__class__) ==id(Retrieval) không thành công.

+8

'siêu (self .__ class__, self)' luôn luôn là sai. Nó sẽ trở thành một vòng lặp vô hạn nếu bạn phân lớp thêm nữa. – Blckknght

+1

Điều gì sẽ xảy ra nếu bạn không phân lớp thêm nữa, đôi khi có được không? – cce

1

Tôi vừa gặp sự cố tương tự, chạy mã của tôi trong sổ ghi chép jupyter. Tôi đã sử dụng tải lại, vì vậy tôi khởi động lại hạt nhân của tôi để theo dõi phản ứng của Eduardo Ivanec để thử và xem đây có phải là vấn đề không. Sau đó, mã của tôi đã bị phá vỡ. Tôi phát hiện ra vấn đề của tôi liên quan đến một số lớp thừa kế, trong đó lớp dưới cùng được xác định ở trên lớp dưới cùng thứ hai trong mô-đun.

class MyClass1(object): 
'''example class 1''' 

class MyClass2(MyClass1): 
'''example class 2''' 
    def __init__(self): 
    super(MyClass2, self).__init__() 

class MyClass4(MyClass3): 
'''example class 4 - no __init__ definition''' 

class MyClass3(MyClass2): 
'''example class 3 - no __init__ definition''' 

Khi tôi di chuyển MyClass4 bên dưới MyClass3, nó đã khắc phục sự cố. Đây có lẽ là một sai lầm tân binh, vì vậy nó có thể sẽ không giải quyết nguyên nhân của vấn đề ban đầu ở trên, nhưng tôi nghĩ rằng tôi sẽ đăng trong trường hợp có những tân binh khác ra khỏi đó, như tôi, những người đang phạm sai lầm tương tự .

(Xin lỗi nếu phong cách của tôi là sai, đây là bài viết đầu tiên của tôi trên Stack Overflow. :))

1

tôi đã có lỗi tương tự sau đó tôi nhận ra rằng tôi đã có lớp trùng lặp (sai lầm của tôi) trong cùng một tập tin. py. Lỗi biến mất khi tôi đổi tên lớp A thứ hai thành lớp B

#Just some example below, not real code 
class A (object): 

    def fun(self): 
     super(A, self).fun() 

class A (object): ##This second class with same name (A) caused the error 

    def some_fun(self,x,y): 
+0

điều này đã sửa nó cho tôi, cảm ơn! – Ghan

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