Type error in __init__ when deriving from two metaclasses
I'd like to make class that derives from PyQt5 QtWidget.QWidget
and an abc.ABCMeta
. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget
and abc.ABCMeta
, and explicitly use that as metaclass for my class.
So far so good, I've defined an QtAbcMeta
class and used this as metaclass
for my ConcreteWidget
class (see below).
import abc
from PyQt5 import QtWidgets, QtCore
class AbstractClass(metaclass=abc.ABCMeta):
def __init__(self, name):
self._name = name
@abc.abstractmethod
def myMethod():
pass
class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
def myMethod():
print("My widget does something")
def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)
if __name__ == "__main__":
main()
However, when I try to call the __init__
method of the QtWidgets.QWidget
method, to set the parent, I get the following TypeError:
Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'
I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__
changed somehow? Any help would be appreciated.
python pyqt pyqt5 metaclass
add a comment |
I'd like to make class that derives from PyQt5 QtWidget.QWidget
and an abc.ABCMeta
. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget
and abc.ABCMeta
, and explicitly use that as metaclass for my class.
So far so good, I've defined an QtAbcMeta
class and used this as metaclass
for my ConcreteWidget
class (see below).
import abc
from PyQt5 import QtWidgets, QtCore
class AbstractClass(metaclass=abc.ABCMeta):
def __init__(self, name):
self._name = name
@abc.abstractmethod
def myMethod():
pass
class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
def myMethod():
print("My widget does something")
def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)
if __name__ == "__main__":
main()
However, when I try to call the __init__
method of the QtWidgets.QWidget
method, to set the parent, I get the following TypeError:
Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'
I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__
changed somehow? Any help would be appreciated.
python pyqt pyqt5 metaclass
What is the purpose ofAbstractClass.__init__(self, name)
? TheAbstractClass
instance is not saved anywhere withinConcreteWidget
.
– John Gordon
Oct 22 '18 at 15:07
In this MVCE the lineAbstractClass.__init__(self, name)
indeed does nothing. In my actual use caseConcreteWidget
inherits from someConcreteClass
, that, in turn, inherits fromAbstractClass
. The__init__
method ofConcreteClass
expected thename
parameter.
– titusjan
Oct 22 '18 at 15:58
add a comment |
I'd like to make class that derives from PyQt5 QtWidget.QWidget
and an abc.ABCMeta
. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget
and abc.ABCMeta
, and explicitly use that as metaclass for my class.
So far so good, I've defined an QtAbcMeta
class and used this as metaclass
for my ConcreteWidget
class (see below).
import abc
from PyQt5 import QtWidgets, QtCore
class AbstractClass(metaclass=abc.ABCMeta):
def __init__(self, name):
self._name = name
@abc.abstractmethod
def myMethod():
pass
class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
def myMethod():
print("My widget does something")
def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)
if __name__ == "__main__":
main()
However, when I try to call the __init__
method of the QtWidgets.QWidget
method, to set the parent, I get the following TypeError:
Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'
I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__
changed somehow? Any help would be appreciated.
python pyqt pyqt5 metaclass
I'd like to make class that derives from PyQt5 QtWidget.QWidget
and an abc.ABCMeta
. Both these classes have their own meta class as type so, according to this page and this SO question, I need to create my own meta class that derives from the meta classes of QWidget
and abc.ABCMeta
, and explicitly use that as metaclass for my class.
So far so good, I've defined an QtAbcMeta
class and used this as metaclass
for my ConcreteWidget
class (see below).
import abc
from PyQt5 import QtWidgets, QtCore
class AbstractClass(metaclass=abc.ABCMeta):
def __init__(self, name):
self._name = name
@abc.abstractmethod
def myMethod():
pass
class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
def myMethod():
print("My widget does something")
def main():
app = QtWidgets.QApplication()
myWidget = ConcreteWidget('my name', parent=None)
if __name__ == "__main__":
main()
However, when I try to call the __init__
method of the QtWidgets.QWidget
method, to set the parent, I get the following TypeError:
Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'
I have no idea what's wrong here. Has the signature of QtWidgets.QWidget.__init__
changed somehow? Any help would be appreciated.
python pyqt pyqt5 metaclass
python pyqt pyqt5 metaclass
edited Nov 23 '18 at 4:27
eyllanesc
74.4k103156
74.4k103156
asked Oct 22 '18 at 14:54
titusjan
3,15511124
3,15511124
What is the purpose ofAbstractClass.__init__(self, name)
? TheAbstractClass
instance is not saved anywhere withinConcreteWidget
.
– John Gordon
Oct 22 '18 at 15:07
In this MVCE the lineAbstractClass.__init__(self, name)
indeed does nothing. In my actual use caseConcreteWidget
inherits from someConcreteClass
, that, in turn, inherits fromAbstractClass
. The__init__
method ofConcreteClass
expected thename
parameter.
– titusjan
Oct 22 '18 at 15:58
add a comment |
What is the purpose ofAbstractClass.__init__(self, name)
? TheAbstractClass
instance is not saved anywhere withinConcreteWidget
.
– John Gordon
Oct 22 '18 at 15:07
In this MVCE the lineAbstractClass.__init__(self, name)
indeed does nothing. In my actual use caseConcreteWidget
inherits from someConcreteClass
, that, in turn, inherits fromAbstractClass
. The__init__
method ofConcreteClass
expected thename
parameter.
– titusjan
Oct 22 '18 at 15:58
What is the purpose of
AbstractClass.__init__(self, name)
? The AbstractClass
instance is not saved anywhere within ConcreteWidget
.– John Gordon
Oct 22 '18 at 15:07
What is the purpose of
AbstractClass.__init__(self, name)
? The AbstractClass
instance is not saved anywhere within ConcreteWidget
.– John Gordon
Oct 22 '18 at 15:07
In this MVCE the line
AbstractClass.__init__(self, name)
indeed does nothing. In my actual use case ConcreteWidget
inherits from some ConcreteClass
, that, in turn, inherits from AbstractClass
. The __init__
method of ConcreteClass
expected the name
parameter.– titusjan
Oct 22 '18 at 15:58
In this MVCE the line
AbstractClass.__init__(self, name)
indeed does nothing. In my actual use case ConcreteWidget
inherits from some ConcreteClass
, that, in turn, inherits from AbstractClass
. The __init__
method of ConcreteClass
expected the name
parameter.– titusjan
Oct 22 '18 at 15:58
add a comment |
2 Answers
2
active
oldest
votes
QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super()
, to ensure all the proper methods in all superclasses are called with their respective parameters.
The creation of super()
has come around exactly to avoid the need to hard-code calls to super-classes __init__
(and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.
The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super
again with the remaining parameters.
QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.
More than that, since Qt classes themselves make use of super, that means your __init__
in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.
So, just rewrite your __init__
method to do it in the "pythonic" way:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)
add a comment |
According to the docs you must pass all the arguments to QWidget although you do not require it:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, name=name, parent=parent)
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses thesuper()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
– titusjan
Nov 14 '18 at 9:42
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52932238%2ftype-error-in-init-when-deriving-from-two-metaclasses%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super()
, to ensure all the proper methods in all superclasses are called with their respective parameters.
The creation of super()
has come around exactly to avoid the need to hard-code calls to super-classes __init__
(and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.
The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super
again with the remaining parameters.
QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.
More than that, since Qt classes themselves make use of super, that means your __init__
in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.
So, just rewrite your __init__
method to do it in the "pythonic" way:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)
add a comment |
QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super()
, to ensure all the proper methods in all superclasses are called with their respective parameters.
The creation of super()
has come around exactly to avoid the need to hard-code calls to super-classes __init__
(and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.
The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super
again with the remaining parameters.
QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.
More than that, since Qt classes themselves make use of super, that means your __init__
in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.
So, just rewrite your __init__
method to do it in the "pythonic" way:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)
add a comment |
QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super()
, to ensure all the proper methods in all superclasses are called with their respective parameters.
The creation of super()
has come around exactly to avoid the need to hard-code calls to super-classes __init__
(and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.
The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super
again with the remaining parameters.
QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.
More than that, since Qt classes themselves make use of super, that means your __init__
in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.
So, just rewrite your __init__
method to do it in the "pythonic" way:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)
QT classes are designed to be used in modern Python code in a cooperative way - and that means they internally make use of Python's super()
, to ensure all the proper methods in all superclasses are called with their respective parameters.
The creation of super()
has come around exactly to avoid the need to hard-code calls to super-classes __init__
(and other overriden methods) with the super-class names, and so that you don't have to worry about the calling order.
The only thing is that each class that is intended to be used as multi-class mixin have to "know" how it about it, extract the named parameters it uses, and call super
again with the remaining parameters.
QT code goes one step further, and checks if all the named parameters for the other classes are presented to it, otherwise it errors.
More than that, since Qt classes themselves make use of super, that means your __init__
in abstract class is being called twice. It won't make a difference in this simple code, but might be a problem in more complicated base classes.
So, just rewrite your __init__
method to do it in the "pythonic" way:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)
answered Nov 13 '18 at 11:47
jsbueno
55.2k677128
55.2k677128
add a comment |
add a comment |
According to the docs you must pass all the arguments to QWidget although you do not require it:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, name=name, parent=parent)
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses thesuper()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
– titusjan
Nov 14 '18 at 9:42
add a comment |
According to the docs you must pass all the arguments to QWidget although you do not require it:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, name=name, parent=parent)
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses thesuper()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
– titusjan
Nov 14 '18 at 9:42
add a comment |
According to the docs you must pass all the arguments to QWidget although you do not require it:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, name=name, parent=parent)
According to the docs you must pass all the arguments to QWidget although you do not require it:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, name=name, parent=parent)
answered Oct 22 '18 at 15:03
eyllanesc
74.4k103156
74.4k103156
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses thesuper()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
– titusjan
Nov 14 '18 at 9:42
add a comment |
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses thesuper()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.
– titusjan
Nov 14 '18 at 9:42
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the
super()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.– titusjan
Nov 14 '18 at 9:42
Thank you for referring me to the docs. The Qt docs, in turn, link to this super considered super article, which was very useful as well. All together this solved my problem but I forgot to reply to you. The answer of jsbueno below reminded me of this. Note that I think his solution is slightly better because is uses the
super()
construct, just as the Qt classes do, so I accepted that as the answer. But yours is good as well, so here's an upvote. Thanks again.– titusjan
Nov 14 '18 at 9:42
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52932238%2ftype-error-in-init-when-deriving-from-two-metaclasses%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What is the purpose of
AbstractClass.__init__(self, name)
? TheAbstractClass
instance is not saved anywhere withinConcreteWidget
.– John Gordon
Oct 22 '18 at 15:07
In this MVCE the line
AbstractClass.__init__(self, name)
indeed does nothing. In my actual use caseConcreteWidget
inherits from someConcreteClass
, that, in turn, inherits fromAbstractClass
. The__init__
method ofConcreteClass
expected thename
parameter.– titusjan
Oct 22 '18 at 15:58