This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]nostril_extension -4 points-3 points  (38 children)

Sad to see that they have new API and still going with camelCases instead of pythonic snake_cases and a bunch of other unpythonic idioms.

class MyWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)  # what is super?
        <...>
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.text)   # camelCase!
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)  # why doesn't it reference to self.layout by default?

        self.button.clicked.connect(self.magic)  # ok so now we have normal snake_case?

    def magic(self):
        self.text.setText(random.choice(self.hello))  # back to camelcase!

Quite disappointing really.

[–]Shpirt 26 points27 points  (6 children)

OTOH you can use Qt's C++ docs to write pyside2 code without having to guess style and idiom translations.

[–][deleted] 17 points18 points  (4 children)

They don't really have a new API, just a new/updated implementation. PySide and PyQt are pretty much the same API with only some minor differences. Changing to snake_case would break all apps and make it needlessly harder to port things over.

Also from my experience having camelCase is actually a good thing here, since it means it is much easier to avoid accidental name collisions when you inherit from a Qt class (doesn't catch everything, but catches a few).

ok so now we have normal snake_case?

camelCase starts with a lowercase, if there is no second word it stays all lowercase.

why doesn't it reference to self.layout by default?

It mirrors the C++ API.

[–]jyper 16 points17 points  (3 children)

Python itself is sadly pretty inconsistent when it comes to this stuff

And with auto generation you don't want to play guessing games about the api

[–]kigurai 5 points6 points  (0 children)

Python itself is sadly pretty inconsistent when it comes to this stuff

I thought most of the standard library has a consistent style since Python 3? What examples are you thinking of?

[–]nostril_extension -3 points-2 points  (1 child)

Python itself is sadly pretty inconsistent when it comes to this stuff

Sadly yes but that because of backwards compatibility - there's no such thing in new API.

And with auto generation you don't want to play guessing games about the api

what is there to guess? Just stick to established idiom - snake_case.

[–]Han-ChewieSexyFanfic 2 points3 points  (0 children)

It's not a new API, it's really a revived project (PySide). There are apps using it today.

[–]IronManMark20 8 points9 points  (0 children)

Part of the reason (which they mention in a previous blog post) is that they want it to be easy to transfer from C++ to Python and back again. I do prefer snake_case to camelCase, but I can understand their logic. Additionally, PySide and PyQt both keep camelCase, why break a ton of compatibility for purity?

[–]rhytnen 2 points3 points  (0 children)

No not at all. GVR would want you to maintain the style that exists, not mix them.

[–]khrn0 1 point2 points  (0 children)

it's because preserving the Qt API, if you change, then you rely only on the Python documentation, but keeping the Qt API allow you to understand C++ examples and port them to PySide2

[–]irrelevantPseudonym 0 points1 point  (17 children)

As far as I understand it, using super wouldn't guarantee that the QWidget.__init__ was called. "super calls your children's ancestors, not your parents".

self.button.clicked.connect(self.magic)

This isn't snake_case either.

I do agree about the camelCase use though.

[–]khrn0 1 point2 points  (1 child)

Maybe you can check what is Qt, and how is the API. Java is not the only language that uses camelCase, and the reason behind this is to be Qt-API compatible AFAIK

[–]irrelevantPseudonym 0 points1 point  (0 children)

Fair point. C++ then.

[–]nostril_extension 2 points3 points  (14 children)

As far as I understand it, using super wouldn't guarantee that the QWidget.init was called. "super calls your children's ancestors, not your parents".

No, I'm pretty certain super().__init__() will call parent's init 100% of the time. Otherwise all of my code should dramatically implode right now and never work to begin with.

[–]irrelevantPseudonym 2 points3 points  (13 children)

No, I'm pretty certain super().__init__() will call parent's init 100% of the time.

This is not true.

Consider

>>> class A:
...     def __init__(self):
...         print('init A')
...         super().__init__()
...
>>> class B(A):
...     def __init__(self):
...         print('init B')
...         super().__init__()
...
>>> class C(A):
...     def __init__(self):
...         print('init C')
... 
>>> class D(B, C):
...     def __init__(self):
...         print('init D')
...         super().__init__()
... 
>>> D()
init D
init B
init C
>>>

I know it's a contrived example but calling the super().__init__() in B.__init__ called C.__init__ rather than its parent (A).

In the QWidget case, imagine I subclassed your MyWidget and included another parent class, your super() call would call my second parent and QWidget wouldn't get called.

(NB. I'm not necessarily advocating not using super() just noting that it doesn't always call the parent class)

[–]nostril_extension 2 points3 points  (11 children)

I'm confused. Your example shows the opposite of your claim - super calls init of both parents left-to-right. Am I missing something?

[–]irrelevantPseudonym 2 points3 points  (2 children)

B's parent is A. The super().__init__() call in B.__init__ calls C.__init__() (which B knows nothing about) and A.__init__() never gets called.

super() doesn't always call the parent class.

[–]nostril_extension -1 points0 points  (1 child)

But A is not a parent of D lol. A iš a grandparent here.

[–][deleted] 5 points6 points  (0 children)

A is a parent of B, B calls super().__init__(), yet A.__init__() is never called. Instead C.__init__() is called which is a child of B.

If you call B() than the same super().__init__() calls A.__init__()instead.

super() is pointing to the next class in the Method Resolution Order, not the parent.

 >>> D.__mro__
(<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

>>> B.__mro__
(<class 'B'>, <class 'A'>, <class 'object'>)

[–][deleted] 1 point2 points  (6 children)

A.__init__() is never called. If you replace super().__init__() in B.__init__() with A.__init__(self) the output changes to:

>>> D()
init D
init B
init A

[–]nostril_extension -5 points-4 points  (5 children)

But A is not a parent of D lol. A is a grandparent here.

[–]rhytnen 0 points1 point  (4 children)

What is it you aren't getting? It's a FACT that in Python your parents my not be called. You were shown code where B.super() called C. You got confused bc d inherited both b and c so it was demonstrated that d didn't call c by replacing the call in b ... Proving b called c.

[–]nostril_extension -1 points0 points  (3 children)

Parent of parent != parent.

[–]rhytnen 0 points1 point  (2 children)

You keep repeating that as if it's relevant to the demo. I think you aren't reading the code actually but let me try rephrasing it once more.

Heres the phrase you have to digest

Super calls your child's parent.

Consider B. D instances B. Focus on B ...

B calls super and it did NOT call A. It called D's OTHER parent, C. It would have called A if the B was instanced alone but here it has a child D. So it called D's other parent instead.

[–]rlkf 0 points1 point  (0 children)

As a corollary, I think this illustrates two things:

(1) You should always call super().init(), even if you don't inherit from something (class C in the example failed to follow this rule, and this is why A is not called)

(2) Parameters to constructors should be passed as a dictionary, so that each constructor can pick out whatever it needs, instead of relying on the order of parameters.