<div dir="ltr">While I disagree with your conclusion, this is a really helpful message because I hadn't realized that QColor can internally represent colors in different ways like that.<br><div><br></div><div>What you seem to have missed is that the color representation format isn't <i>unknowable</i> to __repr__ -- you can check what it is by using the .spec() method. Of course, then your __repr__ would need logic to properly handle all the different specs QColor supports... and both their int- and float-constructor forms... which would be tricky.</div><div><br></div><div>But it's not impossible! And the question interested me enough that I <a href="https://gist.github.com/RoadrunnerWMC/c7ba91a8f31bb1cd9b99b8926d27552c">wrote a proof-of-concept implementation of it.</a></div><div><br></div><div>This QColor.__repr__ gives the shortest* possible repr() for every QColor instance which would eval() back to an identical QColor. More importantly, it's spec-aware, and (for example) correctly handles the case you gave above by showing each color in its true form, even though they're all visually black:</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="font-family:monospace"><span style="color:rgb(0,0,0)">>>> QColor.fromHsv(0, 0, 0)<br>
</span></span><span style="font-family:monospace">PyQt6.QtGui.QColor.fromHsv(0, 0, 0)<br>
</span><span style="font-family:monospace">>>> QColor.fromHsv(1, 0, 0)<br>
</span><span style="font-family:monospace">PyQt6.QtGui.QColor.fromHsv(1, 0, 0)<br>
</span><span style="font-family:monospace">>>> QColor.fromRgb(0, 0, 0)<br>
</span><span style="font-family:monospace">PyQt6.QtGui.QColor(0, 0, 0)</span></blockquote><div><br></div><div><i><font size="1">*ignoring spaces, of course. Also, for outputs that use float values, I'm sure you could chop some digits off of the end, but that sounds hard to do correctly, and I didn't try it</font></i></div><div><br></div><div>Unfortunately, since there are no QColor functions to get the raw 16-bit component values for (say) a HSV color, my __repr__ has to recompute them from the float values. You could argue that that's hardcoding an implementation detail of Qt, but technically, "the components are stored using 16-bit integers" is documented for QColor, so it's not <i>quite</i> that bad. Still, though, if that aspect is problematic, you could fix it by removing that part and having it always use float representations for HSV/CMYK/HSL, though the output will be a bit uglier.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Apr 4, 2023 at 10:38 PM Maurizio Berti <<a href="mailto:maurizio.berti@gmail.com">maurizio.berti@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Il giorno mer 5 apr 2023 alle ore 03:18 RoadrunnerWMC <<a href="mailto:roadrunnerwmc@gmail.com" target="_blank">roadrunnerwmc@gmail.com</a>> ha scritto:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>For what it's worth, I'd also like this. The core geometry classes (QPoint, QRect, QLine, etc. and their float versions) have custom reprs, and I've definitely been bitten by wrongly assuming that QColor has one when debugging in the past.<br>[ ... ]</div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>I think what I'd do, personally, is have it dynamically choose which way to repr itself based on whether all the channels match what Qt would choose for 8-bit input values (aka <font face="monospace">channel * 0x101</font>): </div></div></blockquote><div><br></div><div>I've thought about all that in the past.</div><div><br></div>I made some "shims" on my own as monkey patches for PyQt, as helper/utilities for both programming and debugging, but then I hit some conceptual issues in cases like these.<br></div><div class="gmail_quote"><div>Then I realized that I could only do that whenever I needed it for debugging purposes, and <b>only</b> based on the debugging purposes of a specific context.</div><div><br></div><div>While it is true that *some* constructors give slightly different results depending on the object value, the most important thing is to keep a <b>consistent reliability</b> of the given result.</div><div><br></div><div>For QPoint, that's valid and consistent: <span style="font-family:monospace">QPoint()</span> is and will always be a QPoint with x and y equal to 0.<br></div><div>For QColor, it is not. It is not an "absolute" (or, at least, a "context based absolute", considering the floating point precision issue) value representation, and it's not possible to get one due to its very nature.</div><div><br></div><div>Consider the basic case of HSV:</div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">c0 = QColor.fromHsv(0, 0, 0)</span><br></div><div><span style="font-family:monospace">c1 = QColor.fromHsv(1, 0, 0)</span></div><div><span style="font-family:monospace"></span> <br></div><div>Both the above colors are *visually* identical: they are black. But then:<br></div><div><br></div><div><span style="font-family:monospace">c0 == c1</span><br></div><div><br></div><div>will (not so) obviously return <span style="font-family:monospace">False</span>.</div><div><br></div><div>As you correctly mentioned, <span style="font-family:monospace">__repr__()</span> should always "yield an object with the same value when passed to eval()".</div><div>That consistency is something that should be important for an API.<br></div><div>The representation should be an easy, reliable, consistent "visual" aid. If we want to show different results, but they may still not be that reliable nor consistent (or easily readable), that implementation becomes wrong by principle.</div><div>So, while that monkey patch could be theoretically useful, it wouldn't be valid: it would be only in certain cases, meaning that it should not nor can be part of the API.<br></div><div><br></div><div>Cheers,</div><div>Maurizio<br></div><div> </div></div><span>-- </span><br><div dir="ltr">È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi<br><a href="http://www.jidesk.net" target="_blank">http://www.jidesk.net</a></div></div>
</blockquote></div>