basic Python(ic) inheritance question - python

Quick question about Python(ic) inheritence: what is the difference between the idiom posted here (super(ChildClass,self).method(args)) vs. the one on the Python docs site (ParentClass.method(self,[args]))? Is one more Pythonic than the other?

Using super(ChildClass, self).method(args) allows you to walk the method resolution order and -- if everyone but the last parent uses super -- call every class in the hierarchy exactly once. (Not that super only works with new-style classes.)
Using ParentClass.method(self, args) calls one specific class. It does not work when involved in multiple inheritance.
This article provides some description of the issue and clarifies a lot of issues for some people. I don't agree with all of its conclusions, but it provides good examples and discussion.

Related

Why is super used so much in PySide/PyQt?

Short version (tl;dr)
I am learning PySide, and most online tutorials use super to initialize UI elements. Is this important (i.e., more scalable), or is it a matter of taste?
Clarification: as I make more clear in the detailed version, this is not another generic thread asking when to use super (this has been done before). Rather, given the number of PySide tutorials that use super instead of <class>.__init__, I am trying to figure out if using super is standard in PySide applications? If so, is it because the circumstances where super is called for (involving resolving inheritances) come up a lot specifically in the use of PySide/PyQt? Or is it a matter of taste.
Detailed version
I am new to Python, and presently learning PySide using Zets tutorial (http://zetcode.com/gui/pysidetutorial/firstprograms/). The second example in the tutorial includes:
from PySide import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300,300,250,150)
self.setWindowTitle("PySide 101: Window the First!")
self.show()
app=QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
This works fine, but I have never used super. Hence, I rewrote the above code, successfully replacing super with more standard explicit invocation of the parent class:
QtGui.QWidget.__init__(self)
But as I search the web for PySide tutorials (e.g., http://qt-project.org/wiki/PySide-Newbie-Tutorials), they all include calls to super. My question is: should I use super for PySide scripting?
It seems that super seems most helpful when you have inheritance diamonds, that it tends to resolve instances of multiple inheritance in a reasonable way. Is super used a lot with PySide because there is a preponderance of cases of such diamonds that I will confront with more realistic complicated examples? [Edit: No: see my answer below.]
Why am I even asking? Why not just use super and be done with it?
I am asking because the book I am using to learn Python (Learning Python, by Lutz) spends over 20 pages on the topic of super, and explicitly cautions against using it. He suggests that new Python users go with the more traditional, explicit route before messing with it (e.g., see page 832, and pages 1041-1064 of Learning Python, 5th Edition). He basically paints it as a nonPythonic, arcane, rarely actually needed, new style that you should treat with great caution when just starting out, and thinks it is overused by experienced users.
Further, looking at the source code of two major PySide/PyQt based projects (Spyder and pyqtgraph), neither uses super. One (Spyder) explicitly tells contributors to avoid using it for compatibility reasons (http://code.google.com/p/spyderlib/wiki/NoteForContributors).
Note I link to a closely related post below, but the answer there discusses more generally when you would want to use super (when you have multiple inheritance). My question is whether PySide scripting justifies, or even requires, the use of super in the long term, or whether it is more Pythonic, and better for compatibility reasons, to explicitly name parent classes? Or is it a matter of taste?
If it is frowned upon (as my beginner book suggests) why is it so ubiquitous in PySide tutorials aimed at beginners? If it makes any difference, it seems the people writing these tutorials are seasoned Java programmers, or catering to such programmers. I am not.
Related topics
http://www.riverbankcomputing.com/pipermail/pyqt/2008-January/018320.html
Different ways of using __init__ for PyQt4
Understanding Python super() with __init__() methods
There is nothing wrong with instantiating parent classes in the traditional way, and some things to be said in favor of it. That said, using super simplifies the creation of subclasses, and the future modifications of one's PySide code, and people seem to have latched onto the latter as the overriding factor. This is not specific to Pyside, but to object-oriented programming in Python more generally (as pointed out in Kos's excellent answer).
The potential for simplification of code modification comes because within PySide it is necessary for things to work to define subclasses based on other QtGui objects (e.g., QtQui.QMainWindow and QtGui.QWidget). Further, people tend to futz around with their parent classes enough so that it seems easier to just use super, so that you you don't have to update your __init__ method every time you change parents.
So it isn't a matter of using super to help resolve cases of multiple inheritance, the case where most people agree it is probably best suited. Rather, it is a matter of doing less work within __init__ in case your parent class changes in the future.
Here are the responses from each author, both of whom wrote what I consider to be good PySide tutorials:
Author 1:
I think it is a matter of taste. Earlier tutorials (PyQt and PySide)
used .init and later I switched to super(). I personally
prefer super().
Author 2:
The reason people use super instead of .init(...) is to
avoid making changes if you change what the parent class is, e.g. if
you switch from QVBoxLayout to QHBoxLayout, you only have to change it
in the class definition line, rather than in the init method as
well.
So there you have it. Not these benefits aren't really specific to PySide, but to writing subclasses/inheritance more generally.
I'm not sure what Lutz, who seems very hesitant to endorse the use of super, would say (perhaps using super violates the 'Explicit is better than implicit' maxim).
Update Four Years Later
In retrospect, this debate is sort of over and this question is almost quaint (this was my first question at SO). While there used to be debate about the use of super, these debates are sort of over. Especially in Python 3 super's convenience has proven itself and just makes your code easier to maintain. Because in Qt/Pyside/PyQt framework the use of inheritance from more abstract Qt classes is ubiquitous, this is no small feature. Sure, you will need to be careful when you have crazy lattices of inheritance, but frankly since I asked this question, I have literally never run into this problem, and I currently use super in all my code. It arguably violates the "explicit is better than implicit" maxim, but "Simple is better than complex" and "practicality beats purity" are the overriding factors here (the practical aspect here is "maintainability counts").
Hm, nice one. But IMO it's only barely related to Qt/ PySide.
First, how are these two different? If you have simple inheritance (perhaps not counting "mixins"), then there's no difference in behaviour. A cosmetic difference remains- you don't need to name your base class again - but you do have to name the same class.
The differences start when you have multiple inheritance. Then a chain of super() calls for this hierarchy:
A
/ \
X Y
\ /
Z
can easily proceed like this through super() calls:
A
\
X --- Y
\
Z
without the need of X and Y knowing each other. This relates to the concept of method resolution order that allows a style of programming called "cooperative multiple inheritance" in the Python docs.
If there's a method Foo and implementations in X and Y of that method build upon A's implementation, then Z is easily able to rely on both X and Y without them knowing even about each other. This, however, has an important precondition: Foo has the same (or at least [compatible]) signature in every class, as specified by A's interface where it's initially defined.
The __init__ method is special: technically it works in exactly the same way with super, but! but (more often than not) for subclasses it has a totally different signature. If the subclass' __init__ looks different, then super won't give you anything over explicit base call because you aren't able to use cooperative multitasking anyway.
Note: Python is very atypical in this respect: in most OO languages constructors belong to the class, rather than the instances; in other words most languages rely on their equivalents of __new__ and don't have __init__ at all.
Note 2: I have never seen any real code that would rely of cooperative multiple inheritance. (Single inheritance easily makes enough spaghetti for me ;-))
Also, some good reading:
Method resolution order - what's it all about
Python's Super is nifty, but you can't use it
[

understanding proper python code organization [duplicate]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Much of my programming background is in Java, and I'm still doing most of my programming in Java. However, I'm starting to learn Python for some side projects at work, and I'd like to learn it as independent of my Java background as possible - i.e. I don't want to just program Java in Python. What are some things I should look out for?
A quick example - when looking through the Python tutorial, I came across the fact that defaulted mutable parameters of a function (such as a list) are persisted (remembered from call to call). This was counter-intuitive to me as a Java programmer and hard to get my head around. (See here and here if you don't understand the example.)
Someone also provided me with this list, which I found helpful, but short. Anyone have any other examples of how a Java programmer might tend to misuse Python...? Or things a Java programmer would falsely assume or have trouble understanding?
Edit: Ok, a brief overview of the reasons addressed by the article I linked to to prevent duplicates in the answers (as suggested by Bill the Lizard). (Please let me know if I make a mistake in phrasing, I've only just started with Python so I may not understand all the concepts fully. And a disclaimer - these are going to be very brief, so if you don't understand what it's getting at check out the link.)
A static method in Java does not translate to a Python classmethod
A switch statement in Java translates to a hash table in Python
Don't use XML
Getters and setters are evil (hey, I'm just quoting :) )
Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python
(And if you find this question at all interesting, check out the link anyway. :) It's quite good.)
Don't put everything into classes. Python's built-in list and dictionaries will take you far.
Don't worry about keeping one class per module. Divide modules by purpose, not by class.
Use inheritance for behavior, not interfaces. Don't create an "Animal" class for "Dog" and "Cat" to inherit from, just so you can have a generic "make_sound" method.
Just do this:
class Dog(object):
def make_sound(self):
return "woof!"
class Cat(object):
def make_sound(self):
return "meow!"
class LolCat(object):
def make_sound(self):
return "i can has cheezburger?"
The referenced article has some good advice that can easily be misquoted and misunderstood. And some bad advice.
Leave Java behind. Start fresh. "do not trust your [Java-based] instincts". Saying things are "counter-intuitive" is a bad habit in any programming discipline. When learning a new language, start fresh, and drop your habits. Your intuition must be wrong.
Languages are different. Otherwise, they'd be the same language with different syntax, and there'd be simple translators. Because there are not simple translators, there's no simple mapping. That means that intuition is unhelpful and dangerous.
"A static method in Java does not translate to a Python classmethod." This kind of thing is really limited and unhelpful. Python has a staticmethod decorator. It also has a classmethod decorator, for which Java has no equivalent.
This point, BTW, also included the much more helpful advice on not needlessly wrapping everything in a class. "The idiomatic translation of a Java static method is usually a module-level function".
The Java switch statement in Java can be implemented several ways. First, and foremost, it's usually an if elif elif elif construct. The article is unhelpful in this respect. If you're absolutely sure this is too slow (and can prove it) you can use a Python dictionary as a slightly faster mapping from value to block of code. Blindly translating switch to dictionary (without thinking) is really bad advice.
Don't use XML. Doesn't make sense when taken out of context. In context it means don't rely on XML to add flexibility. Java relies on describing stuff in XML; WSDL files, for example, repeat information that's obvious from inspecting the code. Python relies on introspection instead of restating everything in XML.
But Python has excellent XML processing libraries. Several.
Getters and setters are not required in Python they way they're required in Java. First, you have better introspection in Python, so you don't need getters and setters to help make dynamic bean objects. (For that, you use collections.namedtuple).
However, you have the property decorator which will bundle getters (and setters) into an attribute-like construct. The point is that Python prefers naked attributes; when necessary, we can bundle getters and setters to appear as if there's a simple attribute.
Also, Python has descriptor classes if properties aren't sophisticated enough.
Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python. Correct. Python uses optional arguments instead of method overloading.
The bullet point went on to talk about closure; that isn't as helpful as the simple advice to use default argument values wisely.
One thing you might be used to in Java that you won't find in Python is strict privacy. This is not so much something to look out for as it is something not to look for (I am embarrassed by how long I searched for a Python equivalent to 'private' when I started out!). Instead, Python has much more transparency and easier introspection than Java. This falls under what is sometimes described as the "we're all consenting adults here" philosophy. There are a few conventions and language mechanisms to help prevent accidental use of "unpublic" methods and so forth, but the whole mindset of information hiding is virtually absent in Python.
The biggest one I can think of is not understanding or not fully utilizing duck typing. In Java you're required to specify very explicit and detailed type information upfront. In Python typing is both dynamic and largely implicit. The philosophy is that you should be thinking about your program at a higher level than nominal types. For example, in Python, you don't use inheritance to model substitutability. Substitutability comes by default as a result of duck typing. Inheritance is only a programmer convenience for reusing implementation.
Similarly, the Pythonic idiom is "beg forgiveness, don't ask permission". Explicit typing is considered evil. Don't check whether a parameter is a certain type upfront. Just try to do whatever you need to do with the parameter. If it doesn't conform to the proper interface, it will throw a very clear exception and you will be able to find the problem very quickly. If someone passes a parameter of a type that was nominally unexpected but has the same interface as what you expected, then you've gained flexibility for free.
The most important thing, from a Java POV, is that it's perfectly ok to not make classes for everything. There are many situations where a procedural approach is simpler and shorter.
The next most important thing is that you will have to get over the notion that the type of an object controls what it may do; rather, the code controls what objects must be able to support at runtime (this is by virtue of duck-typing).
Oh, and use native lists and dicts (not customized descendants) as far as possible.
The way exceptions are treated in Python is different from
how they are treated in Java. While in Java the advice
is to use exceptions only for exceptional conditions this is not
so with Python.
In Python things like Iterator makes use of exception mechanism to signal that there are no more items.But such a design is not considered as good practice in Java.
As Alex Martelli puts in his book Python in a Nutshell
the exception mechanism with other languages (and applicable to Java)
is LBYL (Look Before You Leap) :
is to check in advance, before attempting an operation, for all circumstances that might make the operation invalid.
Where as with Python the approach is EAFP (it's easier to Ask for forgiveness than permission)
A corrollary to "Don't use classes for everything": callbacks.
The Java way for doing callbacks relies on passing objects that implement the callback interface (for example ActionListener with its actionPerformed() method). Nothing of this sort is necessary in Python, you can directly pass methods or even locally defined functions:
def handler():
print("click!")
button.onclick(handler)
Or even lambdas:
button.onclick(lambda: print("click!\n"))

Is it a good idea to use super() in Python?

Or should I just explicitly reference the superclasses whose methods I want to call?
It seems brittle to repeat the names of super classes when referencing their constructors, but this page http://fuhm.net/super-harmful/ makes some good arguments against using super().
The book Expert Python Programming has discussed the topic of "super pitfalls" in chapter 3. It is worth reading. Below is the book's conclusion:
Super usage has to be consistent: In a class hierarchy, super should be used everywhere or nowhere. Mixing super and classic calls is a confusing practice. People tend to avoid super, for their code to be more explicit.
Edit: Today I read this part of the book again. I'll copy some more sentences, since super usage is tricky:
Avoid multiple inheritance in your code.
Be consistent with its usage and don't mix new-style and
old-style.
Check the class hierarchy before calling its methods in
your subclass.
You can use super, but as the article says, there are drawbacks. As long as you know them, there is no problem with using the feature. It's like people saying "use composition, not inheritance" or "never use global variables". If the feature exists, there is a reason. Just be sure to understand the why and the what and use them wisely.
super() tries to solve for you the problem of multiple inheritance; it's hard to replicate its semantics and you certainly shouldn't create any new semantics unless you're completely sure.
For single inheritance, there's really no difference between
class X(Y):
def func(self):
Y.func(self)
and
class X(Y):
def func(self):
super().func()
so I guess that's just the question of taste.
I like super() more because it allows you to change the inherited class (for example when you're refactoring and add an intermediate class) without changing it on all the methods.
The problem people have with super is more a problem of multiple inheritance. So it is a little unfair to blame super. Without super multiple inheritance is even worse. Michele Simionato nicely wrapped this up in his blog article on super:
On the other hand, one may wonder if
all super warts aren't hints of some
serious problem underlying. It may
well be that the problem is not with
super, nor with cooperative methods:
the problem may be with multiple
inheritance itself.
So the main lesson is that you should try to avoid multiple inheritance.
In the interest of consistency I always use super, even if for single inheritance it does not really matter (apart from the small advantage of not having to know the parent class name). In Python 3+ super is more convenient, so there one should definitely use super.
Yes, you should use super() over other methods. This is now the standard object inheritance model in Python 3.
Just stick to keyword arguments in your __init__ methods and you shouldn't have too many problems. Additionally you can use **kwargs to support additional parameters that are not defined in levels of the inheritance chain.
I agree that it is brittle, but no less so than using the name of the inherited class.

Would extracting page metadata be a good use of multiple inheritance?

I was wondering if I have a couple of models which both include fields like "meta_keywords" or "slug" which have to do with the web page the model instance will be displayed on, whether it would be advisable to break those page metadata elements out into their own class, say PageMeta, and have my other models subclass those via multiple inheritance?
General advice for a lightly-specified question:
Nontrivial multiple inheritance in Python requires Advanced Techniques to deal with the metaclass/metatype conflict. Look over this recipe from the ActiveState archives and see if it looks like the kind of stuff you like:
Extract from linked recipe:
The simplest case where a metatype
conflict happens is the following.
Consider a class A with metaclass M_A
and a class B with an independent
metaclass M_B; suppose we derive C
from A and B. The question is: what is
the metaclass of C ? Is it M_A or M_B
?
The correct answer (see the book
"Putting metaclasses to work" for a
thoughtful discussion) is M_C, where
M_C is a metaclass that inherits from
M_A and M_B.
However, Python is not that magic, and
it does not automatically create M_C.
Instead, it raises a TypeError,
warning the programmer of the possible
confusion.
Consequently, I recommend limiting your use of multiple inheritance in Python to the following cases:
You must, because your problem domain requires you to combine two separately-maintained single-inheritance libraries.
You have achieved such fluency with metatype and metaclass that you can write recipe 204197 or its equivalent as easily and confidently as you can write a print statement.
Edit:
Here's Guido van Rossum in An Introduction to Python:
It is clear that indiscriminate use of
multiple inheritance is a maintenance
nightmare, given the reliance in
Python on conventions to avoid
accidental name conflicts.
Here he is again in PEP 253, which describes the ideas which were incorporated into Python, but not the implementation:
Metatypes determine various policies
for types, such as what
happens when a type is called, how dynamic types are (whether a
type's dict can be modified after it is created), what the
method resolution order is, how instance attributes are looked
up, and so on.
I'll argue that left-to-right depth-first is not the best
solution when you want to get the most use from multiple
inheritance.
I'll argue that with multiple inheritance, the metatype of the
subtype must be a descendant of the metatypes of all base types.
This does not mean you shouldn't use multiple inheritance; I'm just warning you so you won't be suprised one day to find yourself slapping your forehead and exclaiming "D'oh!
The metatype of one of my subtypes isn't a descendant of the metatypes of all its base types! Don't you hate when that happens?"

"Interfaces" in Python: Yea or Nay? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
So I'm starting a project using Python after spending a significant amount of time in static land. I've seen some projects that make "interfaces" which are really just classes without any implementations. Before, I'd scoff at the idea and ignore that section of those projects. But now, I'm beginning to warm up to the idea.
Just so we're clear, an interface in Python would look something like this:
class ISomething(object):
def some_method():
pass
def some_other_method(some_argument):
pass
Notice that you aren't passing self to any of the methods, thus requiring that the method be overriden to be called. I see this as a nice form of documentation and completeness testing.
So what is everyone here's opinion on the idea? Have I been brainwashed by all the C# programming I've done, or is this a good idea?
I'm not sure what the point of that is. Interfaces (of this form, anyway) are largely to work around the lack of multiple inheritance. But Python has MI, so why not just make an abstract class?
class Something(object):
def some_method(self):
raise NotImplementedError()
def some_other_method(self, some_argument):
raise NotImplementedError()
In Python 2.6 and later, you can use abstract base classes instead. These are useful, because you can then test to see if something implements a given ABC by using "isinstance". As usual in Python, the concept is not as strictly enforced as it would be in a strict language, but it's handy. Moreover there are nice idiomatic ways of declaring abstract methods with decorators - see the link above for examples.
There are some cases where interfaces can be very handy. Twisted makes fairly extensive use of Zope interfaces, and in a project I was working on Zope interfaces worked really well. Enthought's traits packaged recently added interfaces, but I don't have any experience with them.
Beware overuse though -- duck typing and protocols are a fundamental aspect of Python, only use interfaces if they're absolutely necessary.
The pythonic way is to "Ask for forgiveness rather than receive permission". Interfaces are all about receiving permission to perform some operation on an object. Python prefers this:
def quacker(duck):
try:
duck.quack():
except AttributeError:
raise ThisAintADuckException
I don't think interfaces would add anything to the code environment.
Method definition enforcing happens without them. If an object expected to be have like Foo and have method bar(), and it does't, it will throw an AttributeError.
Simply making sure an interface method gets defined doesn't guarantee its correctness; behavioral unit tests need to be in place anyway.
It's just as effective to write a "read this or die" page describing what methods your object needs to have to be compatible with what you're plugging it in as having elaborate docstrings in an interface class, since you're probably going to have tests for it anyway. One of those tests can be standard for all compatible objects that will check the invocation and return type of each base method.
Seems kind of unnecessary to me - when I'm writing classes like that I usually just make the base class (your ISomething) with no methods, and mention in the actual documentation which methods subclasses are supposed to override.
You can create an interface in a dynamically typed language, but there's no enforcement of the interface at compile time. A statically typed language's compiler will warn you if you forget to implement (or mistype!) a method of an interface. Since you receive no such help in a dynamically typed language, your interface declaration serves only as documentation. (Which isn't necessarily bad, it's just that your interface declaration provides no runtime advantage versus writing comments.)
I'm about to do something similar with my Python project, the only things I would add are:
Extra long, in-depth doc strings for each interface and all the abstract methods.
I would add in all the required arguments so there's a definitive list.
Raise an exception instead of 'pass'.
Prefix all methods so they are obviously part of the interface - interface Foo: def foo_method1()
I personally use interfaces a lot in conjunction with the Zope Component Architecture (ZCA). The advantage is not so much to have interfaces but to be able to use them with adapters and utilities (singletons).
E.g. you could create an adapter which can take a class which implements ISomething but adapts it to the some interface ISomethingElse. Basically it's a wrapper.
The original class would be:
class MyClass(object):
implements(ISomething)
def do_something(self):
return "foo"
Then imagine interface ISomethingElse has a method do_something_else(). An adapter could look like this:
class SomethingElseAdapter(object):
implements(ISomethingElse)
adapts(ISomething)
def __init__(self, context):
self.context = context
def do_something_else():
return self.context.do_something()+"bar"
You then would register that adapter with the component registry and you could then use it like this:
>>> obj = MyClass()
>>> print obj.do_something()
"foo"
>>> adapter = ISomethingElse(obj)
>>> print adapter.do_something_else()
"foobar"
What that gives you is the ability to extend the original class with functionality which the class does not provide directly. You can do that without changing that class (it might be in a different product/library) and you could simply exchange that adapter by a different implementation without changing the code which uses it. It's all done by registration of components in initialization time.
This of course is mainly useful for frameworks/libraries.
I think it takes some time to get used to it but I really don't want to live without it anymore. But as said before it's also true that you need to think exactly where it makes sense and where it doesn't. Of course interfaces on it's own can also already be useful as documentation of the API. It's also useful for unit tests where you can test if your class actually implements that interface. And last but not least I like starting by writing the interface and some doctests to get the idea of what I am actually about to code.
For more information you can check out my little introduction to it and there is a quite extensive description of it's API.
Glyph Lefkowitz (of Twisted fame) just recently wrote an article on this topic. Personally I do not feel the need for interfaces, but YMMV.
Have you looked at PyProtocols? it has a nice interface implementation that you should look at.

Categories

Resources