[PyQt] QWidget call other __init__ methods, but why?

Barry Scott barry at barrys-emacs.org
Tue Jun 28 18:20:17 BST 2016


> On 28 Jun 2016, at 18:11, Phil Thompson <phil at riverbankcomputing.com> wrote:
> 
> On 28 Jun 2016, at 5:32 pm, Barry Scott <barry at barrys-emacs.org> wrote:
>> 
>> 
>>> On 28 Jun 2016, at 17:01, Phil Thompson <phil at riverbankcomputing.com> wrote:
>>> 
>>> On 28 Jun 2016, at 4:52 pm, Barry Scott <barry at barrys-emacs.org> wrote:
>>>> 
>>>> Here we have a class that I use in my app. I just fixed a bug
>>>> where wbTrackedModeless.__init__ was called twice as proved
>>>> by using traceback.print_stack().
>>>> 
>>>> class WbTrackedModelessQWidget(QtWidgets.QWidget, WbTrackedModeless):
>>>> def __init__( self ):
>>>>     QtWidgets.QWidget.__init__( self, None ) # line 50
>>>> def closeEvent( self, event ):
>>>>     WbTrackedModeless.closeEvent( self, event )
>>>> 
>>>>     super().closeEvent( event )
>>>> 
>>>> From the definition it looks like wbTrackedModeless.__init__ is 
>>>> not called.
>>>> 
>>>> However here is the stack:
>>>> 
>>>> File "wb_scm_main.py", line 21, in <module>
>>>> sys.exit( wb_main.main( wb_scm_app.WbScmApp, sys.argv ) )
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Common/wb_main.py", line 52, in main
>>>> rc = app.exec_()
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Git/wb_git_ui_actions.py", line 172, in treeTableActionGitLogHistory
>>>> self.main_window.callTreeOrTableFunction( self.treeActionGitLogHistory, self.tableActionGitLogHistory )
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Scm/wb_scm_main_window.py", line 617, in callTreeOrTableFunction
>>>> return fn_tree()
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Git/wb_git_ui_actions.py", line 347, in treeActionGitLogHistory
>>>> self.main_window.getQIcon( 'wb.png' ) )
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Git/wb_git_log_history.py", line 162, in __init__
>>>> super().__init__()
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Common/wb_tracked_qwidget.py", line 50, in __init__
>>>> QtWidgets.QWidget.__init__( self, None )
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Common/wb_tracked_qwidget.py", line 29, in __init__
>>>> self.__trackWidget()
>>>> File "/Users/barry/wc/git/scm-workbench/Source/Common/wb_tracked_qwidget.py", line 34, in __trackWidget
>>>> traceback.print_stack()
>>>> 
>>>> This shows that QtWidgets.QWidget.__init__( self, None ) called WbTrackedModeless.__init__()
>>>> (__trackWidget is first line of __init__ at line 29).
>>>> 
>>>> I guess Phil this is a question for you.
>>>> 
>>>> Why does PyQt call __init__ if there is multiple inheritance? Is this a bug in PyQt?
>>> 
>>> See...
>>> 
>>> http://pyqt.sourceforge.net/Docs/PyQt5/multiinheritance.html
>> 
>> Phil,
>> 
>> I must be missing something important.
>> 
>> https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ shows the base classes being called
>> via explicit super() calls. I cannot find a way to have super() call more then one function.
>> 
>> If I recreate your Person example in pure python I do not see Age.__init__ called.
>> It seems that you are doing something unique in PyQt to get Age called.
>> 
>> Here is the code I used to test the idea in Hettinger’s blog based on your example
>> (but avoiding the PyQy5 implementation):
>> 
>> class QObject(object):
>>   def __init__( self ):
>>       print( 'instance of QObject.__init__' )
>> 
>> class Age(object):
>>   def __init__( self, age=0, **kwds ):
>>       print( 'instance of Age.__init__' )
>> 
>>       self.age = age
>> 
>> class Person(QObject, Age):
>>   def __init__( self, name='', **kwds ):
>>       print( 'instance of Person.__init__' )
>>       super().__init__()
>> 
>>       self.name = name
>> 
>> x = Person( name='Barry', age=21 )
>> print( x.name )
>> print( x.age )
>> 
>> Output:
>> 
>> $ python3.5 qqq.py
>> instance of Person.__init__
>> instance of QObject.__init__
>> <__main__.Person object at 0x1019e6668>
>> 
>> Barry
> 
> You've missed out calls to super().__init__(**kwds)

Are you suggesting the python has code in super() to see that I use **kwds
and call more then one __init__?

You mean like this?

class Person(QObject, Age):
    def __init__( self, name='', **kwds ):
        print( 'instance of Person.__init__' )
        print( kwds )
        super().__init__( **kwds )

        self.name = name

It gets this error:

TypeError: __init__() got an unexpected keyword argument 'age'

Barry



More information about the PyQt mailing list