Gregory Ewing wrote: > Steven D'Aprano wrote: > >> In fairness, "inherit" is standard terminology for the way instances get >> their behaviour from their class. > > I'm not sure that's true, but even if it is, it's > not the same kind of inheritance relationship as > exists between a class and a base class, which was > my point.
I suspect that in Python it actually is, but I don't understand the implementation of attribute look-ups well enough to be sure. >> Also, you can override methods *on the instance*: > > I wouldn't call that a method -- it's just an instance > attribute that happens to be a function. You can tell > it's not a method because it doesn't get a 'self' argument. Actually, if you look at my example, you will see that it is a method and it does get the self argument. Here is the critical code again: from types import MethodType polly.talk = MethodType( lambda self: print("Polly wants a spam sandwich!"), polly) The MethodType constructor takes a function and an instance, and returns a method bound to that instance. >> In Python, obj.talk performs the following (grossly simplified) >> process: >> >> * search the instance for an attribute "talk" >> * search the class >> * search all the base classes >> * fail >> >> (simplified because I have ignored the roles of __getattr__ and >> __getattribute__, of metaclasses, and the descriptor protocol) > > By ignoring the descriptor protocol, you're simplifying > away something very important. It's the main thing that > makes the instance-of relation different from the > subclass-of relation. That's certainly not correct, because Python had classes and instances before it had descriptors! Classes and instances go back to pre-1.5 days, while descriptors were only introduced in 2.2. Besides, descriptors are handled by the metaclass, so we could write a metaclass that doesn't handle them. >> The normal way of giving a class methods that are callable from the class >> is to define them on the class with the classmethod or staticmethod >> decorators. Using a metaclass is usually overkill :-) > > True, but I was trying to illustrate the symmetry > between classes and instances, how the classic OOP > ideas of Smalltalk et al are manifest in Python, > and to show that classes *can* "participate fully > in OOP" just like any other objects if you want them > to. Python's "class methods" are strange beasts that > don't have an equivalent in the classic OOP model, > so they would only have confused matters. Fair point about classmethods. I think you're actually underestimating how close the symmetry between new- style classes and instances actually is in Python. > And there are cases where you *do* need a metaclass, > such as giving a __dunder__ method to a class, so it's > useful to know how to do it just in case. I don't understand this. I write dunder methods all the time. Ah wait, I think I've got it. If you want (say) your class object itself to support (say) the + operator, it isn't enough to write a __add__ method on the class, you have to write it on the metaclass. -- Steven -- https://mail.python.org/mailman/listinfo/python-list