4

For an amusing (and valid but unrelated) reason I want to do the following:

class Head(type, tuple):
    pass

But this results in

TypeError: multiple bases have instance lay-out conflict

(on python3.3 and python2.7)

Any way around this?

For the curious I want to create something that behaves like Mathematica expression (Derivative[1][g][x] being g'(x)). I know there are other ways, but for educational purposes I insist on this one.

Thomas Fenzl
  • 4,342
  • 1
  • 17
  • 25
Krastanov
  • 6,479
  • 3
  • 29
  • 42
  • 2
    Why do you think that doing this is a good way to achieve the `Derivative[1][g][x]` thing? – BrenBarn Jun 02 '13 at 17:39
  • 1
    Inheriting from `type` is utterly pointless; it doesn't give you anything that `tuple` doesn't already give you. – Martijn Pieters Jun 02 '13 at 17:51
  • @BrenBarn, I want a class (Derivative) with instances (Derivative[1]) which themselves are classes with instances like Derivative[1][g] which themselves are etc, etc. I am not saying it is a good way to solve the problem, but it is an amusing way to do it. Basically I want metaclass (so I use `type`) with `__eq__` of a `tuple` (because I save all the args in a tuple). I can use a tuple as a property of the class, but this is not as nice as the class itself being a subclass of tuple. So I do not see why subclassing `type` is pointless. How else can I create a metaclass (without hacks)? – Krastanov Jun 02 '13 at 18:48
  • Why do you need instances of Derivative to be classes? Just make a class called with a `__getitem__` that returns an instance of another class with a `__getitem__`, etc. It may be "amusing" to try to do it this way, but it won't work, as you've seen. – BrenBarn Jun 02 '13 at 18:53
  • I was using mathematica syntax in the examples concerning mathematica. So it will not be `__getitem__` but rather `__call__`. And this is not enough, because I want uniformity in the traversal of the trees. As I said, I know there are other ways to do this, but for aesthetic and educational purposes I prefer this way. Moreover, this is the semantically correct way to implement an expression tree where the operators themselves can be whole other trees. – Krastanov Jun 02 '13 at 19:02
  • 1
    I'd say a tuple being a property of the class is nicer than inheriting from tuple. The only extra thing you'd get from inheriting from tuple is to be able to say `(Derivative(1)(g)(x))[2] == x`, which I think is obfuscated. If you need to get at the nth parameter, then make a named method to do so. If you really prefer the array access syntax you can put it back in with `__getitem__`. So I'd say if anything you want to inherit from type and not tuple. – morningstar Jun 02 '13 at 19:31
  • @morningstar, while you slightly misinterpreted the syntax that I want, I tend to agree with you that I should just use a tuple as a property if subclassing is not possible. For what is worth, I want `type(Derivative(1)(g)(x)) == Derivative(1)(g)` and `Derivative(1)(g)(x)[:] == (x,)`. – Krastanov Jun 02 '13 at 19:35

1 Answers1

3

I can't seem to find an appropriate link to it, but the point is that Python doesn't support multiple inheritence of several built-in types. You can't create a class that inherit both from "type" and "tuple", or from "int" and "str", or most other combinations. There is a mostly internal reason related to the internal layout of the instances: an "int" object's memory layout contains storage for the integer value; but this is incomptible with the layout of a "str" object, which contains storage for the characters. It's not possible to create an instance of a class that would inherit from both, because we don't know which memory layout it should have.

Compare this with the memory layout of an instance of a class that inherits only from object, directly or indirectly. Such an instance only needs storage for a __dict__, which is a dictionary containing the attributes. This works without problem for whatever multiple inheritance diagram.

These two cases have been combined (in Python 2.2) into the following "best-effort" appraoch: inheritence is only possible if there is at most one built-in base type. In this case, the memory layout can start with the layout expected for this built-in type, and contain the __dict__ afterwards to store any attribute required by the other base classes.

Armin Rigo
  • 12,048
  • 37
  • 48
  • Thanks, this is exactly what I wanted to know. If you find a reference I would be great to add it here. – Krastanov Jun 03 '13 at 11:22