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 2008年08月29日 22:39 by gumtree, last changed 2022年04月11日 14:56 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| issue3734.patch | mark.dickinson, 2009年02月10日 23:31 | |||
| Messages (8) | |||
|---|---|---|---|
| msg72169 - (view) | Author: Blair (gumtree) | Date: 2008年08月29日 22:39 | |
The following is quoted from the Python docs (ref/numeric_types): "Note: If the right operand's type is a subclass of the left operand's type and that subclass provides the reflected method for the operation, this method will be called before the left operand's non-reflected method. This behavior allows subclasses to override their ancestors' operations." My issue is that the built-in complex type does not respect this rule (see code below). Note that float can be subclassed using the method shown below and the rules are applied correctly. It seems that it is only a problem with complex. class xcomplex( complex ): def __new__(cls,*args,**kwargs): return complex.__new__(cls,*args,**kwargs) def __coerce__(self,other): t = complex.__coerce__(self,other) try: return (self,xcomplex(t[1])) except TypeError: return t def __add__(self,x): return xcomplex( complex.__add__(self,x) ) def __radd__(self,x): return xcomplex( complex.__radd__(self,x) ) print type(z + xz) # gives complex when xcomplex is required |
|||
| msg81571 - (view) | Author: Daniel Diniz (ajaksu2) * (Python triager) | Date: 2009年02月10日 18:12 | |
Confirmed in trunk. Here's a copy-n-past'able testcase: class xcomplex( complex ): def __new__(cls,*args,**kwargs): return complex.__new__(cls,*args,**kwargs) def __coerce__(self,other): t = complex.__coerce__(self,other) try: return (self,xcomplex(t[1])) except TypeError: return t def __add__(self,x): return xcomplex( complex.__add__(self,x) ) def __radd__(self,x): return xcomplex( complex.__radd__(self,x) ) class xfloat(float): def __new__(cls,*args,**kwargs): return float.__new__(cls,*args,**kwargs) def __coerce__(self,other): t = float.__coerce__(self,other) try: return (self,float(t[1])) except TypeError: return t def __add__(self,x): return xfloat( float.__add__(self,x) ) def __radd__(self,x): return xfloat( float.__radd__(self,x) ) z = 1j xz = xcomplex(1j) f = 1.0 xf = xfloat(1.0) print type(z + xz) print type(f + xf) |
|||
| msg81584 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2009年02月10日 19:21 | |
I'll take a look. |
|||
| msg81609 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2009年02月10日 22:23 | |
So there's a hint about what's happening here at the bottom of the section http://docs.python.org/reference/datamodel.html#id5 of the docs, where it says: """In the current implementation, the built-in numeric types int, long and float do not use coercion; the type complex however does use it. The difference can become apparent when subclassing these types. Over time, the type complex may be fixed to avoid coercion. [...]""" In the OPs example, when z + xz is evaluated, xz is (successfully) coerced to type complex, and then complex.__add__ is called to do the addition as usual. There's definitely (at least) a documentation bug here, given that at the same place as referenced above it says: """New-style classes (those derived from object) never invoke the __coerce__() method in response to a binary operator; the only time __coerce__() is invoked is when the built-in function coerce() is called.""" At the level of the C code, the practical difference between complex and (for example) float is that the float type has Py_TPFLAGS_CHECKTYPES set, and all arithmetic operations do their own conversions. The complex type doesn't set Py_TPFLAGS_CHECKTYPES, and so (contrary to the documentation) relies on complex_coerce to do any conversions. |
|||
| msg81613 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2009年02月10日 23:31 | |
I think this issue comes down to a doc fix, though I've opened issue 5211 for anyone who fancies having a go at removing coercion from the complex type. Here's a doc patch. |
|||
| msg81614 - (view) | Author: Blair (gumtree) | Date: 2009年02月11日 00:00 | |
While Mark Dickinson's patch fixes the documentation, it does not offer a solution to the original problem, which was rooted in a need to provide special behaviour based on the numeric types. I made the original posting because I hoped that this problem could be resolved. |
|||
| msg81634 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2009年02月11日 08:58 | |
[gumtree] > [...] does not offer > a solution to the original problem, which was rooted in a need to > provide special behaviour based on the numeric types. I made the > original posting because I hoped that this problem could be resolved. Please see issue 5211 for further discussion. |
|||
| msg81902 - (view) | Author: Georg Brandl (georg.brandl) * (Python committer) | Date: 2009年02月13日 10:45 | |
Applied doc patch in r69573. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:56:38 | admin | set | github: 47984 |
| 2009年02月13日 10:45:04 | georg.brandl | set | status: open -> closed resolution: fixed messages: + msg81902 |
| 2009年02月11日 08:58:41 | mark.dickinson | set | messages: + msg81634 |
| 2009年02月11日 00:00:05 | gumtree | set | messages: + msg81614 |
| 2009年02月10日 23:31:57 | mark.dickinson | set | files:
+ issue3734.patch assignee: mark.dickinson -> georg.brandl messages: + msg81613 keywords: + patch nosy: + georg.brandl |
| 2009年02月10日 22:23:05 | mark.dickinson | set | messages: + msg81609 |
| 2009年02月10日 19:21:52 | mark.dickinson | set | assignee: mark.dickinson messages: + msg81584 |
| 2009年02月10日 18:12:32 | ajaksu2 | set | nosy:
+ mark.dickinson, ajaksu2 messages: + msg81571 components: + Interpreter Core, - None versions: + Python 2.6, Python 2.7, - Python 2.5 |
| 2008年08月29日 22:39:09 | gumtree | create | |