On 18 October 2015 at 05:55, Steven D'Aprano <steve@pearwood.info> wrote:
On Sat, Oct 17, 2015 at 03:45:19PM -0600, Eric Snow wrote:
So, would it make sense to establish some concrete guidelines about when to use type(obj) vs. obj.__class__? If so, what would those be? It may also be helpful to enumerate use cases for "type(obj) is not obj.__class__".
I for one would like to see a definitive explanation for when they are different, and when you should use one or the other. The only obvious example I've seen is the RingBuffer from the Python Cookbook:
It looks like this example just assigns to the existing __class__ attribute, to switch to a different class. I haven’t seen this ability mentioned in the documentation, but I suspect it is meant to be supported. However assigning to __class__ like that should automatically update the type() return value, so type(ring_buffer) == ring_buffer.__class__ is still maintained. Perhaps some of this confusion comes from Python 2. I don’t know the details, but I know in Python 2, type() can do something different, so you have to use __class__ directly if you want to be compatible with Python 2 classes. But in Python 3 code I prefer using direct function calls like type() to “special attributes” like __class__ where practical. The documentation says that __*__ names are reserved for Python and its built-in library, rather than user code. So user code that creates a class attribute or property called __class__ is asking for trouble IMO, and we shouldn’t spend much effort accommodating such cases. For __repr__() I would use type(), which seems to agree with what object.__repr__() uses.