Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This can be done with Python's multiple inheritance if none of the methods need to invoke <code>super()</code>.</p> <pre><code>class Dog(object): name = "Spot" class Cat(object): name = "Whiskers" class SpeakingAnimalMixin(object): def speak(self): print "My name is", self.name, "and I can speak!" class SpeakingDog(SpeakingAnimalMixin, Dog): pass class SpeakingCat(SpeakingAnimalMixin, Cat): pass SpeakingDog().speak() </code></pre> <blockquote> <p>My name is Spot and I can speak!</p> </blockquote> <hr> <p>If you do need to invoke <code>super()</code> from a method then you need to create the class dynamically. This works fine, but the generated class's name will be less helpful and IDEs and other static analysis tools may be less useful.</p> <p>You can create the class using a function, passing the superclass as an argument:</p> <pre><code>def make_speaking_animal_class(SpeechlessAnimal): class SpeakingAnimal(SpeechlessAnimal): def get_name(self): return "Speaking " + super(SpeakingAnimal, self).get_name() def speak(self): print "My name is", self.get_name() return SpeakingAnimal class Dog(object): def get_name(self): return "Spot" class Cat(object): def get_name(self): return "Whiskers" SpeakingDog = make_speaking_animal_class(Dog) SpeakingCat = make_speaking_animal_class(Cat) SpeakingCat().speak() </code></pre> <blockquote> <p>My name is Speaking Whiskers</p> </blockquote> <p>However as mentioned, the class's <code>__name__</code> attribute may not be what you expect.</p> <pre><code>print SpeakingDog print SpeakingDog() </code></pre> <pre class="lang-none prettyprint-override"><code>&lt;class '__main__.SpeakingAnimal'&gt; &lt;__main__.SpeakingAnimal object at 0x1004a3b50&gt; </code></pre> <p>You can fix this by assigning them unique <code>__name__</code> attributes yourself:</p> <pre><code>SpeakingDog.__name__ = 'SpeakingDog' print SpeakingDog </code></pre> <pre class="lang-none prettyprint-override"><code>&lt;class '__main__.SpeakingDog'&gt; </code></pre> <p><sup>(Credit to <a href="https://stackoverflow.com/users/12266/andrew-jaffe">Andrew Jaffe</a> for suggesting this in an answer, but he deleted it.)</sup></p> <p>There's another way to create a class dynamically, but I discourage you from using it unless you need to; it's even less clear. <a href="http://docs.python.org/2/library/functions.html#type" rel="nofollow noreferrer">The <code>type</code> function</a> has a second use, apart from its main one of determining the class of an object: it can be used to dynamically create a new class.</p> <p>When used this way, the <code>type</code> function takes three parameters:</p> <ul> <li><code>name</code>, the <code>__name__</code> the new class will have.</li> <li><code>bases</code>, a tuple of of base classes that the new class will inherit from.</li> <li><code>dict</code>, a dictionary containing the methods and attributes the new class will have.</li> </ul> <p>You could use it like this:</p> <pre><code>def make_speaking_animal_class(SpeechlessAnimal, name): def get_name(self): return "Speaking " + super(SpeakingAnimal, self).get_name() def speak(self): print "My name is", self.get_name() bases = (SpeechlessAnimal,) # We need to define SpeakingAnimal in a variable so that get_name can refer # to it for the super() call, otherwise we could just return it directly. SpeakingAnimal = type(name, bases, { 'get_name': get_name, 'speak': speak }) return SpeakingAnimal class Dog(object): def get_name(self): return "Spot" class Cat(object): def get_name(self): return "Whiskers" SpeakingDog = make_speaking_animal_class(Dog, 'SpeakingDog') SpeakingCat = make_speaking_animal_class(Cat, 'SpeakingCat') SpeakingDog().speak() SpeakingCat().speak() </code></pre> <blockquote> <p>My name is Speaking Spot<br> My name is Speaking Whiskers</p> </blockquote>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload