New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
__class__ assignment error message confusing #48850
Comments
ob.__class__ = ob2
gives some confusing TypeError messages. >>> c.__class__ = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ must be set to new-style class, not 'int' object Problem: 'new-style' is obsolete in 3.0. It is also too inclusive... >>> c.__class__ = object
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types object *is* 'new-style'. I presume 'heap type' means 'class defined by Proposal: when someone tries to set __class__ to an inappropriate TypeError: __class__ must be set to a class defined by a class where 'object', without the brackets, is added for non-classes, as it is >>> c.__class__ = object
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types C, the class of c, *is* a heap type. The different problem, the target TypeError: __class__ assignment: only for instances of classes defined |
Related issue that applies to recent 2.x. Language/data model/Objects, |
Here comes a patch, changing the behaviour to: ./python -q
>>> class C:
... pass
...
>>> (1).__class__ = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ must be set to a class defined by a class statement, not 'int' object
>>> (1).__class__ = object
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: class__ must be set to a class defined by a class statement, not 'object'
>>> (1).__class__ = C
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for instances of classes defined by class statements |
This is not really accurate: >>> class x(int): pass
...
>>> class y(object): pass
...
>>> x().__class__ = y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: 'x' object layout differs from 'y'
>>> y().__class__ = x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: 'y' object layout differs from 'x' |
The error messages are different now: >>> class C: pass
...
>>> c = C()
>>> c.__class__ = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ must be set to a class, not 'int' object
>>> c.__class__ = object
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment only supported for mutable types or ModuleType subclasses
>>> |
I neglected to mention above what c is. I Irit guessed right as >>> class C: pass
...
>>> c = C() is what I (also) usually do for examples and testing. Removing "new-style" elsewhere solved the issue with the error message for "ob.__class__ = non_class_object". The new error message for "ob.__class__ = someclass" replaces 'heap' with 'mutable'. But it can still be confusing as the qualification in __class__ assignment only supported for mutable types or ModuleType subclasses applies to both type(ob) and someclass and the same error is given if either does not qualify. The use of the plural 'types' allows but does not mandate this interpretation. Also, "mutable types" means that the types are mutable, not their instances. Although 'list' is sometimes referred to as a 'mutable type' because its instances are, 'list' itself is not mutable and does not qualify here. I am closing this issue, which is about the error message, because the new message is accurate when understood. I cannot think of any better one-line message. Explaining the background needed to understand should be done elsewhere. Andre, I nosied you in case the above would help you improve Friendly's explanation of this error. I was a bit confused myself until I did more experiments. Note: Even when type(ob) and someclass both 'qualify', the assignment will fail if instances are 'incompatible'. Let M be a subclass of types.ModuleType. c.__class__ = M # fails with TypeError: __class__ assignment: 'M' object layout differs from 'C' The difference is obvious by looking as dir(c) and dir(M('somename')). |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: