<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div></div><br><div class="gmail_quote"><div class="gmail_attr" dir="ltr">On Mon, 18 Feb 2019 at 17:27, Phil Thompson <<a href="mailto:phil@riverbankcomputing.com">phil@riverbankcomputing.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">On 18 Feb 2019, at 4:51 pm, J Barchan <<a href="mailto:jnbarchan@gmail.com" target="_blank">jnbarchan@gmail.com</a>> wrote:<br>
> <br>
> <br>
> <br>
> On Thu, 14 Feb 2019 at 17:48, J Barchan <<a href="mailto:jnbarchan@gmail.com" target="_blank">jnbarchan@gmail.com</a>> wrote:<br>
> <br>
> <br>
> On Thu, 14 Feb 2019 at 14:56, Vincent Vande Vyvre <<a href="mailto:vincent.vande.vyvre@telenet.be" target="_blank">vincent.vande.vyvre@telenet.be</a>> wrote:<br>
> Le 14/02/19 à 14:56, J Barchan a écrit :<br>
>> <br>
>> <br>
>> On Thu, 14 Feb 2019 at 13:34, J Barchan <<a href="mailto:jnbarchan@gmail.com" target="_blank">jnbarchan@gmail.com</a>> wrote:<br>
>> This may be as much a Python question as a PyQt one. I come from a C++ background. I do not understand the syntax/code I need in a class I am deriving from a PyQt class to allow a new parameter to be passed to the constructor.<br>
>> <br>
>> I see that I asked this question a long time ago at <a href="https://stackoverflow.com/questions/45999732/python3-typing-overload-and-parameters" target="_blank" rel="noreferrer">https://stackoverflow.com/questions/45999732/python3-typing-overload-and-parameters</a> but never got an answer.<br>
>> <br>
>> I now want to sub-class from QListWidgetItem. That starts with these constructors:<br>
>> <br>
>> QListWidgetItem(QListWidget *parent = nullptr, int type = Type)<br>
>> QListWidgetItem(const QString &text, QListWidget *parent = nullptr, int type = Type)<br>
>> QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = nullptr, int type = Type)<br>
>> QListWidgetItem(const QListWidgetItem &other)<br>
>> <br>
>> My sub-class should still support these constructors. In addition to the existing text, I want my sub-class to be able to store a new optional value. At minimum/sufficient I want a new possible constructor like one of the following:<br>
>> <br>
>> MyListWidgetItem(const QString &text, const QVariant &value, QListWidget *parent = nullptr, int type = Type)<br>
>> # or<br>
>> MyListWidgetItem(const QString &text, QVariant value = QVariant(), QListWidget *parent = nullptr, int type = Type)<br>
>> <br>
>> So for Python I know I start with a typing overload definition (for my editor) like <br>
>> <br>
>> @typing.overload<br>
>> def MyListWidgetItem(self, text: str, value: typing.Any, parent: QListWidget=None, type: int=Type)<br>
>> pass<br>
>> <br>
>> Then I get to the definition bit. To cater for everything am I supposed to do:<br>
>> <br>
>> def __init__(self, *__args)<br>
>> # Now what??<br>
>> super().__init__(__args)<br>
>> <br>
>> Is that how we do it? Is it then my responsibility to look at __args[1] to see if it's my value argument? And remove it from __args before passing it onto super().__init__(__args)?<br>
>> <br>
>> Or, am I not supposed to deal with __args, and instead have some definition with all possible parameters explicitly and deal with them like that?<br>
>> <br>
>> Or what? This is pretty fundamental to sub-classing to add parameters where you don't own the code of what you're deriving from. It's easy in C-type languages; I'm finding it real to hard to understand what I can/can't/am supposed to do for this, I'd be really gratefully for a couple of lines to show me, please...! :)<br>
>> <br>
>> -- <br>
>> Kindest,<br>
>> Jonathan<br>
>> <br>
>> P.S.<br>
>> I think I got my overload a bit mixed up. I meant I (think I) will have:<br>
>> <br>
>> class MyListWidgetItem(QListWidgetItem)<br>
>> @typing.overload<br>
>> def __init__(self, text: str, value: typing.Any, parent: QListWidget=None, type: int=Type)<br>
>> pass<br>
>> <br>
>> def __init__(self, *__args)<br>
>> # Now what??<br>
>> super().__init__(__args)<br>
>> <br>
>> <br>
>> -- <br>
>> Kindest,<br>
>> Jonathan<br>
>> <br>
>> <br>
>> _______________________________________________<br>
>> PyQt mailing list <br>
>> <a href="mailto:PyQt@riverbankcomputing.com" target="_blank">PyQt@riverbankcomputing.com</a><br>
>> <a href="https://www.riverbankcomputing.com/mailman/listinfo/pyqt" target="_blank" rel="noreferrer">https://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br>
> Hi,<br>
> <br>
> I use just that:<br>
> <br>
> class ListItem(QListWidgetItem):<br>
> def __init__(self, img, text, parent=None):<br>
> super().__init__(parent)<br>
> icon = QIcon()<br>
> icon.addPixmap(QPixmap(img), QIcon.Normal, QIcon.Off)<br>
> self.setIcon(icon)<br>
> self.setText(text)<br>
> <br>
> The arguments are examples, not mandatory.<br>
> <br>
> Vincent<br>
> <br>
> _______________________________________________<br>
> PyQt mailing list <a href="mailto:PyQt@riverbankcomputing.com" target="_blank">PyQt@riverbankcomputing.com</a><br>
> <a href="https://www.riverbankcomputing.com/mailman/listinfo/pyqt" target="_blank" rel="noreferrer">https://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br>
> <br>
> Hello Vincent,<br>
> <br>
> Thank you for replying. I'm afraid the suggestion you give is so significantly different from what I am asking that I don't see how it addresses it. I could write a lot about the differences between what you show and what I am asking. Here are some:<br>
> • I don't see that you're adding any argument that QListWidgetItem does not already accept?? Please bear in mind there is already QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = nullptr, int type = Type). I want to add a new argument.<br>
> • Your super().__init__() is not passing anything other than parent to the base constructor, yet the base constructor accepts more arguments than that, just like your derived class does.<br>
> • (untested) it seems to me that your code will break the existing QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent = nullptr, int type = Type) constructor overload (i.e. what happens when I pass a QIcon() as the img parameter to your ListItem constructor?)<br>
> • how does your code allow for the existing QListWidgetItem(const QString &text, QListWidget *parent = nullptr, int type = Type) overload<br>
> • you are not using any typing hints so this will lose my editor's context completion<br>
> I don't know whether one of us is misunderstanding the other, or we're on different planes? :)<br>
> <br>
> -- <br>
> Kindest,<br>
> Jonathan<br>
> <br>
> May I politely try bumping this question? I have had one answer, which as far as I understand does not work.<br>
> <br>
> How exactly could/would you derive from QListWidgetItem from Python to add a "value" parameter in a constructor? I could do it easily from C++. It does seem to me this is at least partly a PyQt question, I've tried asking it at <a href="https://stackoverflow.com/questions/54746309/python-3-add-argument-when-subclassing-from-complex-arguments" target="_blank" rel="noreferrer">https://stackoverflow.com/questions/54746309/python-3-add-argument-when-subclassing-from-complex-arguments</a> , I'm getting comments like "If PyQT makes it impossible to use common Python idioms then I can't do much about it actually <g>" and "The OP needs to have a re-think and accept that some compromises are inevitable when trying to fake c++ idioms in pure python."<br>
> <br>
> This is a bit above my head. I'm either getting a generic answer which is inadequate or no answer or told it may not be doable. I don't understand this. Can someone tell me how to add the argument I have in mind, or something similar (you do need to read through the precise example I am asking about), or explain why it can't be done, or something? I should be so obliged!<br>
<br>
I know it's not what you are asking but things get much easier if you require the value to be specified as a keyword argument...<br>
<br>
def __init__(self, *args, value, **kwargs):<br>
super().__init__(*args, **kwargs)<br>
print("Got value", value)<br>
<br>
...and it makes your code more readable.<br>
<br>
Phil</blockquote></div><div><br></div><div><div class="gmail_default" style="font-family:tahoma,sans-serif">Thank you for responding. Ahh, maybe we're getting somewhere...! :)</div><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div><div class="gmail_default" style="font-family:tahoma,sans-serif">So, you're suggesting I forget about positional and add an optional <font face="monospace,monospace">value=...</font> keyword argument? So instead of calling it like:<br></div><blockquote style="margin-right:0px" dir="ltr"><div class="gmail_default" style="font-family:tahoma,sans-serif"><font face="monospace,monospace">addItem(MyListWidgetItem(<em>text</em>, <em>value</em>))</font></div></blockquote><div class="gmail_default" style="font-family:tahoma,sans-serif">caller will go:<br></div><blockquote style="margin-right:0px" dir="ltr"><div class="gmail_default" style="font-family:tahoma,sans-serif"><font face="monospace,monospace">addItem(MyListWidgetItem(<em>text</em>, <strong>value=</strong><em>value</em>))</font></div></blockquote><div class="gmail_default" style="font-family:tahoma,sans-serif">I guess that's not too bad. I'm not used to this at all, it's not how I'd do it in C++!</div><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div><div class="gmail_default" style="font-family:tahoma,sans-serif">So I'm looking at your definition closely:</div><div class="gmail_default" style="font-family:tahoma,sans-serif"><br><font face="monospace,monospace"> def __init__(self, *args, value, **kwargs):<br> super().__init__(*args, **kwargs)<br> print("Got value", value)</font><br></div><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div><div class="gmail_default" style="font-family:tahoma,sans-serif">So putting that <font face="monospace,monospace">value</font> after the <font face="monospace,monospace">*args </font>and before the <font face="monospace,monospace">**kwargs </font>makes it so it is a specifically-named argument, is that what is going on? I was thinking I'd have to search/index/remove from the <font face="monospace,monospace">**kwargs </font>to find my named parameter, this seems nicer....</div><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div><div class="gmail_default" style="font-family:tahoma,sans-serif">So this is how you would do it (simplest/best) if you were me and wanted to add this <em>value</em> parameter?<br></div><br clear="all"><br>-- <br></div><div class="gmail_signature" dir="ltr"><div dir="ltr"><div><div dir="ltr"><div><span style="font-family:tahoma,sans-serif">Kindest,</span></div><div><span style="font-family:tahoma,sans-serif">Jonathan</span></div></div></div></div></div></div></div></div>