473,385 Members | 1,727 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Operator Overloading

I wonder if the following quotation from the Python Reference Manual
(release 2.3.3) about operator overloading is true :

"For example, if a class defines a method named __getitem__(), and x
is
an instance of this class, then x[i] is equivalent to
x.__getitem__(i)"

Consider the following code:
from Numeric import *
a = array([0.5])
a array([ 0.5]) from Numeric import *
a = array([0.5])
a[0] 0.5

but
a.__getitem__(0) Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __getitem__

I probably understand why the call to __getitem__: there is no
__dict__ attribute in the variable a and not even a __class__
attribute to find what
the class of the variable a is:
a.__dict__ Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __dict__ a.__class__ Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __class__

I didn't know that you could have an instance without a __class__
attribute ... Anyway, if the __class__ attribute was defined, I guess
that the call to a.__getitem__(0) would succeed because "__getitem__"
belongs to the __dict__
of the type of a.
"__getitem__" in type(a).__dict__

True

But then, why does the call to a[0] succeed ? It should be exactly
equivalent
to a.__getitem__[0], right ?
Jul 18 '05 #1
8 4024
Sebastien Boisgerault schrieb:
I wonder if the following quotation from the Python Reference Manual
(release 2.3.3) about operator overloading is true :

"For example, if a class defines a method named __getitem__(), and x
is
an instance of this class, then x[i] is equivalent to
x.__getitem__(i)"

[...]
from Numeric import *
a = array([0.5])
a[0]
0.5

but

a.__getitem__(0)


Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __getitem__


The quotation above is true. Short form:

IF __getitem__ in dict THEN [] works.

What you are wondering about is the opposite direction

IF [] works THEN __getitem__ in dict.

but this is not what the Python Reference Manual says. Im not a
Numeric expert but AFAIK Numeric arrays are basically C arrays
having [] intrinsically so there's no need no deliver it via
__getitem__.

Mit freundlichen Gruessen,

Peter Maas

--
-------------------------------------------------------------------
Peter Maas, M+R Infosysteme, D-52070 Aachen, Tel +49-241-93878-0
E-mail 'cGV0ZXIubWFhc0BtcGx1c3IuZGU=\n'.decode('base64')
-------------------------------------------------------------------
Jul 18 '05 #2
Peter Maas a écrit :
Sebastien Boisgerault schrieb:
I wonder if the following quotation from the Python Reference Manual
(release 2.3.3) about operator overloading is true :

"For example, if a class defines a method named __getitem__(), and x
is
an instance of this class, then x[i] is equivalent to
x.__getitem__(i)"


[...]
> from Numeric import *
> a = array([0.5])
> a[0]

0.5

but

> a.__getitem__(0)

Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __getitem__

The quotation above is true. Short form:

IF __getitem__ in dict THEN [] works.


That's not true !!! I's true only for classes defined in Python. If you
try to define a class in C, defining the __getitem__ method does not
lead to the existence of "[]". But when you define "[]" it creates the
"__getitem__" method. This is part of the reason why you cannot dervie
from two types if they derives from different classes written in another
language and imported in Python (just try to create a class deriving
from list and dict ...).

Pierre
Jul 18 '05 #3
Peter Maas wrote:
What you are wondering about is the opposite direction

IF [] works THEN __getitem__ in dict.

but this is not what the Python Reference Manual says. Im not a
Numeric expert but AFAIK Numeric arrays are basically C arrays
having [] intrinsically so there's no need no deliver it via
__getitem__.


This is correct, and true of any C extension - classes implemented in C only
need to define the appropriate function pointers in their type structures in
order for Python to find the relevant methods.

Classes that are being *nice* about it put in the actual magic method names as
well (e.g. try "list.__getitem__"), but it is by no means required.

Cheers,
Nick.
Jul 18 '05 #4
Peter Maas <pe***@somewhere.com> wrote in message news:<co**********@swifty.westend.com>...
Sebastien Boisgerault schrieb:
I wonder if the following quotation from the Python Reference Manual
(release 2.3.3) about operator overloading is true :

"For example, if a class defines a method named __getitem__(), and x
is an instance of this class, then x[i] is equivalent to
x.__getitem__(i)" [...]
>from Numeric import *
>a = array([0.5])
>a[0]


0.5

but

>a.__getitem__(0)


Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __getitem__


The quotation above is true. Short form:

IF __getitem__ in dict THEN [] works.


Not exactly the same assertion:
replace "__getitem__ in dict" by "__getitem__ in the class dict"
and more importantly "[] works" by "[] and __getitem__" are *equivalent*.

Here, "__getitem__" does belongs to type(a).__dict__,
so "[]" and "__getitem__" should work exactly the same
according to the reference, but they don't.
[...]
but this is not what the Python Reference Manual says. Im not a
Numeric expert but AFAIK Numeric arrays are basically C arrays
having [] intrinsically so there's no need no deliver it via
__getitem__.


I would buy your argument if I couldn't find the "__getitem__" method.
But it does exist ! Except that it is hidden is the class __dict__ and
apparently cannot be recovered from the instance.__getitem__ call ...

Thanks for your help,

SB
Jul 18 '05 #5
Nick Coghlan <nc******@email.com> wrote in message news:<41***********************@per-qv1-newsreader-01.iinet.net.au>...
Peter Maas wrote:
What you are wondering about is the opposite direction

IF [] works THEN __getitem__ in dict.

but this is not what the Python Reference Manual says. Im not a
Numeric expert but AFAIK Numeric arrays are basically C arrays
having [] intrinsically so there's no need no deliver it via
__getitem__.


This is correct, and true of any C extension - classes implemented in C only
need to define the appropriate function pointers in their type structures in
order for Python to find the relevant methods.

Classes that are being *nice* about it put in the actual magic method names as
well (e.g. try "list.__getitem__"), but it is by no means required.


Nick, Pierre, Peter,

Thanks for your answers. I guess that in the case of the Numeric
package, there was at least the *intent* to support __getitem__
because it is provided at the class level (which is not required,
right ?):
from Numeric import *
a = array([3.14])
Array = type(a)
a.__getitem__(0) Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __getitem__ Array.__getitem__(a,0)

3.14

I guess that everything would work as expected if __class__ was defined at
the instance level ...

Regards,

SB
Jul 18 '05 #6
Sebastien Boisgerault schrieb:
Peter Maas <pe***@somewhere.com> wrote in message news:<co**********@swifty.westend.com>...
Sebastien Boisgerault schrieb: [...]but this is not what the Python Reference Manual says. Im not a
Numeric expert but AFAIK Numeric arrays are basically C arrays
having [] intrinsically so there's no need no deliver it via
__getitem__.

I would buy your argument if I couldn't find the "__getitem__" method.
But it does exist ! Except that it is hidden is the class __dict__ and
apparently cannot be recovered from the instance.__getitem__ call ...


This is strange because it's not the same behaviour as in a pure
Python class. If you really need __getitem__ you could write a
wrapper (or derive, not sure if it is possible):

class sbArray(object):
def __init__(self, plainarray):
self.data = plainarray
def __getitem__(self, idx):
return self.data[idx]

:)

--
-------------------------------------------------------------------
Peter Maas, M+R Infosysteme, D-52070 Aachen, Tel +49-241-93878-0
E-mail 'cGV0ZXIubWFhc0BtcGx1c3IuZGU=\n'.decode('base64')
-------------------------------------------------------------------
Jul 18 '05 #7
Sebastien Boisgerault wrote:
from Numeric import *
a = array([3.14])
Array = type(a)
a.__getitem__(0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: __getitem__
Array.__getitem__(a,0)


3.14


That's just. . . odd. It's possible that array has a custom __getattr__ or
__getattribute__ implementation that is not falling back to the class dictionary
correctly. The direct class access doesn't use the custom handlers, and gets the
correct answer. However, you'd need someone more familiar with Numeric than I am
to say exactly what is going on.

If Numeric has its own mailing list, I'd try asking there.

Cheers,
Nick.
Jul 18 '05 #8
On 25 Nov 2004 06:35:23 -0800, bo******@isia.cma.fr (Sebastien Boisgerault) wrote:
Peter Maas <pe***@somewhere.com> wrote in message news:<co**********@swifty.westend.com>...
Sebastien Boisgerault schrieb:
> I wonder if the following quotation from the Python Reference Manual
> (release 2.3.3) about operator overloading is true :
>
> "For example, if a class defines a method named __getitem__(), and x
> is an instance of this class, then x[i] is equivalent to
> x.__getitem__(i)"

[...]
>>>>from Numeric import *
>>>>a = array([0.5])
>>>>a[0]
>
> 0.5
>
> but
>
>
>>>>a.__getitem__(0)
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: __getitem__


The quotation above is true. Short form:

IF __getitem__ in dict THEN [] works.


Not exactly the same assertion:
replace "__getitem__ in dict" by "__getitem__ in the class dict"
and more importantly "[] works" by "[] and __getitem__" are *equivalent*.

Here, "__getitem__" does belongs to type(a).__dict__,
so "[]" and "__getitem__" should work exactly the same
according to the reference, but they don't.
[...]
but this is not what the Python Reference Manual says. Im not a
Numeric expert but AFAIK Numeric arrays are basically C arrays
having [] intrinsically so there's no need no deliver it via
__getitem__.


I would buy your argument if I couldn't find the "__getitem__" method.
But it does exist ! Except that it is hidden is the class __dict__ and
apparently cannot be recovered from the instance.__getitem__ call ...

Thanks for your help,

SB

I believe the new style classes require looking for a descriptor (which
includes functions, which become bound methods via their descriptor nature)
with the attribute name given, before grabbing something from the instance dict.
Otherwise instance attributes would always shadow corresponding method or property
names, and those things wouldn't work, or would work as in the old style classes.

Therefore looking for __getitem__ is a little trickier than it might seem.
It has to work like any other name, so a.__getitem__ can't be treated differently from a.foo.

So as you noticed, the first place to look is in type(a).__dict__ (which is
also an attribute lookup BTW, with name '__dict__' which could be a descriptor
too, but we'll ignore that for the moment. See further below for that).

Consider that given
import Numeric
a = Numeric.array([0.5])
a array([ 0.5])

this
a[0] 0.5

produces the same result as this
type(a).__dict__['__getitem__'].__get__(a, type(a)).__call__(0) 0.5

So what happens when we look for type(a).__dict__? '__dict__' is just a name,
so we have to look for a method or property in the chain of base classes.
The buck presumably stops at some base class descriptor named __dict__, if any,
and that descriptor, if present, determines what you get. The chain of search
for type(a).__dict__ presumably starts looking in type(type(a)).__dict__, but
type(type(a)) <type 'type'>

is already at the end of the chain.
type(type(a)).__dict__ <dictproxy object at 0x0090B4D0>

Remember, we're going to look _in_ the __dict__, not _for_ it here ;-)

But this has already been processed through the attribute magic, so to see
what '__dict__' is without that processing, we use the proxy to look it up:
type(type(a)).__dict__['__dict__'] <attribute '__dict__' of 'type' objects>

Which is a descriptor if it has a __get__ method: type(type(a)).__dict__['__dict__'].__get__ <method-wrapper object at 0x0090B4D0>

Sure enough, so we pass type(a) and its type to that, and get back type(a).__dict__ the long way:
type(type(a)).__dict__['__dict__'].__get__(type(a), type(type(a))) <dictproxy object at 0x009015B0>

now we can look for __getitem__ in that: type(type(a)).__dict__['__dict__'].__get__(type(a), type(type(a)))['__getitem__'] <slot wrapper '__getitem__' of 'array' objects>

Which being the function of a method, should have a descriptor's __get__ method, by which
to become a bound method:
type(type(a)).__dict__['__dict__'].__get__(type(a), type(type(a)))['__getitem__'].__get__ <method-wrapper object at 0x0090B4D0>

So we pass it the instance and its type: type(type(a)).__dict__['__dict__'].__get__(type(a), type(type(a)))['__getitem__'].__get__(a, type(a)) <method-wrapper object at 0x009015B0>

Which should have a __call__ method if it's callable: type(type(a)).__dict__['__dict__'].__get__(type(a), type(type(a)))['__getitem__'].__get__( a, type(a)).__call__
<method-wrapper object at 0x0090B4D0>

Which we can call with the index type(type(a)).__dict__['__dict__'].__get__(type(a), type(type(a)))['__getitem__'].__get__( a, type(a)).__call__(0)
0.5

Fortunately, we don't normally have to think about all that when we write
a[0]

0.5

;-)

Caveat: this is not based on reading the code internals, so I could be misinterpreting surface
appearances, but at least it ought to be clear that a[0] involves a lot of dynamic decisions that
might ordinarlily not be taken, but which must be allowed for in looking for an innocent method
like __getitem__ ;-)

[Hm, just looking in oubox: this apparently didn't go out the other day.]

Regards,
Bengt Richter
Jul 18 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
by: Edward Diener | last post by:
Is there a way to override the default processing of the assignment operator for one's own __value types ? I realize I can program my own Assign method, and provide that for end-users of my class,...
34
by: Pmb | last post by:
I've been working on creating a Complex class for my own learning purpose (learn through doing etc.). I'm once again puzzled about something. I can't figure out how to overload the assignment...
16
by: gorda | last post by:
Hello, I am playing around with operator overloading and inheritence, specifically overloading the + operator in the base class and its derived class. The structure is simple: the base class...
2
by: pmatos | last post by:
Hi all, I'm overloading operator<< for a lot of classes. The question is about style. I define in each class header the prototype of the overloading as a friend. Now, where should I define the...
67
by: carlos | last post by:
Curious: Why wasnt a primitive exponentiation operator not added to C99? And, are there requests to do so in the next std revision? Justification for doing so: C and C++ are increasingly used...
3
by: karthik | last post by:
The * operator behaves in 2 different ways. It is used as the value at address operator as well as the multiplication operator. Does this mean * is overloaded in c?
5
by: Jerry Fleming | last post by:
As I am newbie to C++, I am confused by the overloading issues. Everyone says that the four operators can only be overloaded with class member functions instead of global (friend) functions: (), ,...
3
by: y-man | last post by:
Hi, I am trying to get an overloaded operator to work inside the class it works on. The situation is something like this: main.cc: #include "object.hh" #include "somefile.hh" object obj,...
9
by: sturlamolden | last post by:
Python allows the binding behaviour to be defined for descriptors, using the __set__ and __get__ methods. I think it would be a major advantage if this could be generalized to any object, by...
8
by: Wayne Shu | last post by:
Hi everyone, I am reading B.S. 's TC++PL (special edition). When I read chapter 11 Operator Overloading, I have two questions. 1. In subsection 11.2.2 paragraph 1, B.S. wrote "In particular,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.