This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2017年05月02日 14:30 by Jim Fasarakis-Hilliard, last changed 2022年04月11日 14:58 by admin.
| Messages (8) | |||
|---|---|---|---|
| msg292764 - (view) | Author: Jim Fasarakis-Hilliard (Jim Fasarakis-Hilliard) * | Date: 2017年05月02日 14:30 | |
Currently the first lines in PyObject_IsSubClass are:
/* We know what type's __subclasscheck__ does. */
if (PyType_CheckExact(cls)) {
/* Quick test for an exact match */
if (derived == cls)
return 1;
return recursive_issubclass(derived, cls);
}
The if (derived == cls) runs only if PyType_CheckExact is True which doesn't hold for any classes with a custom metaclass. As a result, a check of the form issubclass(Sequence, Sequence) will take a slow path that invokes __subclasscheck__.
I'm not sure if this was placed inside there due to some wild edge-case, though. PyObject_IsInstance uses the same trick and does so outside the if (PyType_CheckExact(cls)) check.
I'll gladly submit a PR if this indeed needs fixing and not by design.
|
|||
| msg293244 - (view) | Author: Jim Fasarakis-Hilliard (Jim Fasarakis-Hilliard) * | Date: 2017年05月08日 17:24 | |
Additional question, are tests required to check this behavior? (Also, bumping) |
|||
| msg293379 - (view) | Author: Raymond Hettinger (rhettinger) * (Python committer) | Date: 2017年05月10日 05:38 | |
Will deeply grokking this code, I would say to leave it alone. The test seems reasonable and is very fast (likely free of cost on many machines). |
|||
| msg293390 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) | Date: 2017年05月10日 08:31 | |
Jim doesn't propose to remove fast test, it proposes to add a test for fast path for avoiding invoking __subclasscheck__ (this is slow). This can change semantic, but isinstance() already contains such fast path. This is similar to testing "elem is seq[i]" before "elem == seq[i]" when search in sequences. This optimization changes semantic for NaNs. Does a "Not-A-Class" class which is not a subclass of itself (issubclass(C, C) returns False) makes any sense? |
|||
| msg293422 - (view) | Author: Raymond Hettinger (rhettinger) * (Python committer) | Date: 2017年05月10日 14:40 | |
My point was that it isn't wise to propose PRs for code you don't fully understand (he said, "I'm not sure if this was placed inside there due to some wild edge-case,"). |
|||
| msg293471 - (view) | Author: Jim Fasarakis-Hilliard (Jim Fasarakis-Hilliard) * | Date: 2017年05月11日 02:50 | |
> he said, "I'm not sure if this was placed inside there due to some wild edge-case,"
As a new contributor, I'll always lean on the side of me not seeing something rather than confidently stating that something is definitely wrong. I'm new, the code-base is 20 years old and worked on by a dozen of experienced devs :-)
> Does a "Not-A-Class" class which is not a subclass of itself (issubclass(C, C) returns False) makes any sense?
I'm not sure. Apart from the performance impact, there's a behavioral discrepancy between isinstance and issubclass as you also stated.
In isinstance, __instancecheck__ doesn't *always* get a chance to override the behavior. The `if type(inst) == Cls` [1] stops it before it gets a chance.
In issubclass, __subclasscheck__ does override it:
class Meta(type):
def __instancecheck__(self, other):
print("invoked")
return False
def __subclasscheck__(self, other):
print("invoked")
return False
class Cls(metaclass=Meta):
pass
isinstance(Cls(), Cls)
True
issubclass(Cls, Cls)
invoked
False
So, I guess the question might be re-framed to: Is it guaranteed that __instancecheck__ and __subclasscheck__ are *always* called?
If yes: PyObject_IsInstance should be tweaked.
If no: PyObject_IsSubclass should be tweaked.
p.s Should I maybe move this to python-dev?
[1]: https://github.com/python/cpython/blob/master/Objects/abstract.c#L2338
|
|||
| msg306785 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) | Date: 2017年11月23日 07:06 | |
Yes, please move this to Python-Dev. |
|||
| msg331638 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) | Date: 2018年12月11日 16:13 | |
Any progress? |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:45 | admin | set | github: 74416 |
| 2018年12月11日 16:13:42 | serhiy.storchaka | set | messages:
+ msg331638 versions: + Python 3.8, - Python 3.7 |
| 2017年11月23日 07:06:21 | serhiy.storchaka | set | messages: + msg306785 |
| 2017年05月11日 02:50:16 | Jim Fasarakis-Hilliard | set | messages: + msg293471 |
| 2017年05月10日 14:40:31 | rhettinger | set | messages: + msg293422 |
| 2017年05月10日 08:31:18 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages: + msg293390 |
| 2017年05月10日 05:38:33 | rhettinger | set | priority: normal -> low nosy: + georg.brandl, pitrou messages: + msg293379 |
| 2017年05月09日 16:32:30 | rhettinger | set | nosy:
+ rhettinger |
| 2017年05月08日 17:24:09 | Jim Fasarakis-Hilliard | set | messages: + msg293244 |
| 2017年05月02日 14:35:12 | serhiy.storchaka | set | type: behavior -> performance title: Move quick test in PyObject_IsSubClass outside if PyType_CheckExact guard -> Move quick test in PyObject_IsSubClass outside of PyType_CheckExact guard |
| 2017年05月02日 14:30:45 | Jim Fasarakis-Hilliard | create | |