473,769 Members | 3,923 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Overloading operators on the rigth.

In a nutshell:
What is the equivalent of __radd__ (wich overloads the right hand side
of +) when overloading the comparison operators <,>,== and so on. My
first guess __rlt__ for
overloading the rigth hand side of < did not work.
Expanded version:
In a class of numbers I have been able to overload the four arithmetic
operators +,-,* and / by defining the methods __add__ and __radd__
(etc..) in my class. This enables me to evaluate expressions
"instance_of_my _class+"instanc e_of_my_class" ,"instance + non_instance"
(with __add__) as well as "non_instance+i nstance"(with __radd__).
But my guess to define the method __rlt__ in my class in order to be
able to evaluate expressions "non_instan ce < instance" did not work.
So what are the names (if they exist at all) of the comparison operators
<,>,== and so on, when one wants to exend their rigth hand side to a
user defined (instance of a) class?

In case of direct e-mail response please remove the french translation
of nospam in my signature, that is to say the string :
pasdepourriels.

Jul 18 '05 #1
13 2010
denis wendum <we**********@p asdepourriels.e df.fr> wrote:
But my guess to define the method __rlt__ in my class in order to be
able to evaluate expressions "non_instan ce < instance" did not work.
Sensible guess, but not the way things work.
So what are the names (if they exist at all) of the comparison operators
<,>,== and so on, when one wants to exend their rigth hand side to a
user defined (instance of a) class?


Here's how to find out:
class foo: .... def __getattr__(sel f, name):
.... print 'looking for %r' % name
.... raise AttributeError, name
.... f=foo()
12 < f looking for '__gt__'
looking for '__coerce__'
looking for '__cmp__'
True


See what's happening here? After determining that int (the type of 12)
cannot deal with comparing 12 with an instance of foo, Python's
implementation of < turns to the right hand side... and asks for a
__gt__ method first! Makes sense, because 12 < f is presumably going to
be the same thing as f > 12 ... once it doesn't find __gt__ the
implementation continues by trying to coerce f to an int (by checking if
class foo supports __coerce__) and lastly by trying for the old-style
comparison method __cmp__. But you presumably don't care about that;
rather, the gist of it is: write your __gt__ -- that will also be used
as your "__rlt__" -- and so on!
Alex
Jul 18 '05 #2
On Tue, 12 Oct 2004 16:06:52 +0200, al*****@yahoo.c om (Alex Martelli) wrote:
denis wendum <we**********@p asdepourriels.e df.fr> wrote:
But my guess to define the method __rlt__ in my class in order to be
able to evaluate expressions "non_instan ce < instance" did not work.


Sensible guess, but not the way things work.
So what are the names (if they exist at all) of the comparison operators
<,>,== and so on, when one wants to exend their rigth hand side to a
user defined (instance of a) class?


Here's how to find out:
class foo:... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
... f=foo()
12 < flooking for '__gt__'
looking for '__coerce__'
looking for '__cmp__'
True
See what's happening here? After determining that int (the type of 12)
cannot deal with comparing 12 with an instance of foo, Python's
implementati on of < turns to the right hand side... and asks for a
__gt__ method first! Makes sense, because 12 < f is presumably going to
be the same thing as f > 12 ... once it doesn't find __gt__ the
implementati on continues by trying to coerce f to an int (by checking if
class foo supports __coerce__) and lastly by trying for the old-style
comparison method __cmp__. But you presumably don't care about that;
rather, the gist of it is: write your __gt__ -- that will also be used
as your "__rlt__" -- and so on!


On my system, (NT4, python 2.3.2) what really happens for newstyle classes
isn't apparent from that experiment:
class foo(object): ... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
... f=foo()
12 < f True

The old style does work much the same (but note the default end result ;-)
Is that a 2.3.2 bug?
class foo: ... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
... f=foo()
12 < f

looking for '__gt__'
looking for '__coerce__'
looking for '__cmp__'
False

Regards,
Bengt Richter
Jul 18 '05 #3
I think it's a difference in new-style classes that __getattr__ doesn't
have a chance to run when searching for special methods.

I'm sure this is documented, but I didn't see it in
http://python.org/2.2.2/descrintro.html

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFBbIUEJd0 1MZaTXX0RAgC4AJ 9VDc64p8uTr+2Rq IjDqs/wjdcN4wCgiGBs
iyu6fjYUTutHsSO BvTFE1ds=
=Cnor
-----END PGP SIGNATURE-----

Jul 18 '05 #4
Bengt Richter <bo**@oz.net> wrote:
...
> class foo:... def __getattr__(sel f, name): ... On my system, (NT4, python 2.3.2) what really happens for newstyle classes
isn't apparent from that experiment:


Heh, of course not -- the main difference between old-style and
new-style classes is that, for the latter, implicit lookup of special
methods when needed for operations starts with the *class*, not with the
*instance*. This is a fix of a long-standing design bug, because the
old rule was just impossible to apply consistently -- if calling X meant
looking for X.__call__ rather than X.__class__.__c all__, how could you
ever instantiate X by calling it, when X is a class whose _instances_
are meant to be callable, for example?

Since this has been discussed many times on this group, as well as in
presentations, articles, websites, books, ..., I didn't think it was
necessary to dwell on the issue again, considering it really did not
affect the answer requested by the original poster; apparently I was
wrong in so thinking. _Sigh_ -- next time somebody criticizes my posts
as being too long, I'll retort that of course they are, if I must keep
repeating such issues!-)

I just used an old-style class because, that way, I could show the
lookups happening without having to code a custom metaclass. The
special names being looked for are just the same, whether for classic or
newstyle classes, anyway -- all that changes is _where_ they're looked
up (starting on the instance, vs starting on the class).

>>> class foo(object): ... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
... >>> f=foo()
>>> 12 < f

True

The old style does work much the same (but note the default end result ;-)
Is that a 2.3.2 bug?


No bug: comparisons between objects of disparate types give essentially
arbitrary results (repeatable within one run, but, at least in theory,
potentially different among runs of the same program, I believe).
Alex
Jul 18 '05 #5
On Wed, 13 Oct 2004 10:18:28 +0200, al*****@yahoo.c om (Alex Martelli) wrote:
Bengt Richter <bo**@oz.net> wrote:
...
>>>> class foo:
>... def __getattr__(sel f, name): ...
On my system, (NT4, python 2.3.2) what really happens for newstyle classes
isn't apparent from that experiment:
Heh, of course not -- the main difference between old-style and
new-style classes is that, for the latter, implicit lookup of special
methods when needed for operations starts with the *class*, not with the

Well, it always starts with the class if there's no attribute on the instance,
but the key is whether the "implicit lookup" for methods needed for operations
uses an overridable __getattribute_ _ somewhere, or just chases down the bases
chain looking for the actual __gt__ or whatever, not allowing a hook to synthesize
a result.*instance*. This is a fix of a long-standing design bug, because the
old rule was just impossible to apply consistently -- if calling X meant
looking for X.__call__ rather than X.__class__.__c all__, how could you
ever instantiate X by calling it, when X is a class whose _instances_
are meant to be callable, for example?

Since this has been discussed many times on this group, as well as in
presentation s, articles, websites, books, ..., I didn't think it was
necessary to dwell on the issue again, considering it really did not
affect the answer requested by the original poster; apparently I was
wrong in so thinking. _Sigh_ -- next time somebody criticizes my posts
as being too long, I'll retort that of course they are, if I must keep
repeating such issues!-)
I have suspected you of having voice recognition input ;-)
I don't type that fast, unfortunately.
I just used an old-style class because, that way, I could show the
lookups happening without having to code a custom metaclass. The Could you show such a metaclass? I have tried a few things and not succeeded.
It almost makes me think there is no place to hook the internal __getattribute_ _
that looks for the methods for code generated from 12<f and the like.
I'd be interested in seeing it.
special names being looked for are just the same, whether for classic or ^^^^^^^^^^^^^^ but maybe not the same order, see belownewstyle classes, anyway -- all that changes is _where_ they're looked
up (starting on the instance, vs starting on the class).

>>> class foo(object):

... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
...
>>> f=foo()
>>> 12 < f

True

The old style does work much the same (but note the default end result ;-)
Is that a 2.3.2 bug?


No bug: comparisons between objects of disparate types give essentially
arbitrary results (repeatable within one run, but, at least in theory,
potentially different among runs of the same program, I believe).

I tried a class with all the methods explicit, and then removed them:
class foo(object): ... def __gt__(self, other): print 'gt'
... def __coerce__(self , other): print 'coerce'
... def __cmp__(self, other): print 'cmp'
... f=foo()
12<f gt

Ok, so it looked for __gt__ first. Remove that. del foo.__gt__ 12<f cmp
It seems to have looked for __cmp__ second, unlike in your post:

+---<from your post>------------------
Here's how to find out:
class foo: .... def __getattr__(sel f, name):
.... print 'looking for %r' % name
.... raise AttributeError, name
.... f=foo()
12 < f looking for '__gt__'
looking for '__coerce__'
looking for '__cmp__'
True +-------------------------------------

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: an integer is required
(didn't like none back from cmp, presumably)

Ok, remove __cmp__ del foo.__cmp__
One left: 12<f

coerce
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: __coerce__ didn't return a 2-tuple

NBD, but perhaps the order change is a version difference?
Not that the OP was asking any of this ;-)

Regards,
Bengt Richter
Jul 18 '05 #6
Bengt Richter <bo**@oz.net> wrote:
On Wed, 13 Oct 2004 10:18:28 +0200, al*****@yahoo.c om (Alex Martelli) wrote:
Bengt Richter <bo**@oz.net> wrote:
...
>>>> class foo:
>... def __getattr__(sel f, name): ...
On my system, (NT4, python 2.3.2) what really happens for newstyle classes
isn't apparent from that experiment:


Heh, of course not -- the main difference between old-style and
new-style classes is that, for the latter, implicit lookup of special
methods when needed for operations starts with the *class*, not with the

Well, it always starts with the class if there's no attribute on the instance,


I find this a strange meaning for the word "start". To ensure the
instance doesn't have the attribute, that's where (conceptually) one
could say the lookup "starts", I think.
but the key is whether the "implicit lookup" for methods needed for
operations uses an overridable __getattribute_ _ somewhere, or just chases
down the bases chain looking for the actual __gt__ or whatever, not
allowing a hook to synthesize a result.
Actually, it reaches right into the appropriate slot of the type
structure. The slots are generated or changed when the type (i.e., the
class object) is generated or changed. So, it may be improper on my
part to call this procedure a 'lookup'.
I just used an old-style class because, that way, I could show the
lookups happening without having to code a custom metaclass. The

Could you show such a metaclass? I have tried a few things and not
succeeded. It almost makes me think there is no place to hook the internal
__getattribute_ _ that looks for the methods for code generated from 12<f
and the like. I'd be interested in seeing it.


I think I'd basically have to repeat what types.ClassType is doing --
essentially, prefill all slots with functions that _do_ perform the
lookups. To be honest, I haven't tried to see if that strategy hits any
snags, I just don't think it would.

special names being looked for are just the same, whether for classic or

^^^^^^^^^^^^^^
but maybe not the same order, see below
newstyle classes, anyway -- all that changes is _where_ they're looked
up (starting on the instance, vs starting on the class).


You're right -- coercion is "fading" so it's now attempted _after_ 3-way
comparison rather than before; so the 'where' isn't quite _all_ that's
changed (I had never coded nor seen a classic class which depended on
coercion for its comparisons, which may explain though not excuse my
imprecision).

NBD, but perhaps the order change is a version difference?
Yep, it's part of coercion slowly going away.
Not that the OP was asking any of this ;-)


No, but they may still be meaningful in some cases, of course.
Alex
Jul 18 '05 #7
On Wed, 13 Oct 2004 10:52:57 GMT, bo**@oz.net (Bengt Richter) wrote:
[...]

NBD, but perhaps the order change is a version difference?
Not that the OP was asking any of this ;-)

Posted before recalling that the order difference showed up
on my system between old-style and new-style, both on 2.3.2,
so at least what I saw is not a version difference.

Someplace in classobject vs typeobject or such?

Regards,
Bengt Richter
Jul 18 '05 #8


Alex Martelli a écrit :
denis wendum <we**********@p asdepourriels.e df.fr> wrote:

Here's how to find out:
class foo: ... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
... f=foo()
12 < f looking for '__gt__'
looking for '__coerce__'
looking for '__cmp__'
True


See what's happening here?

Alex


Many thanks for your answer: you didn't just gave me the fish I asked but also

showed me how to use a net for catching other fish.

It seems I triggered a fierce debate with my question, but as far as I'm
concerned your example worked perfectly.

Jul 18 '05 #9
denis wendum <we**********@p asdepourriels.e df.fr> wrote:
...
Here's how to find out:
>> class foo: ... def __getattr__(sel f, name):
... print 'looking for %r' % name
... raise AttributeError, name
...
>> f=foo()
>> 12 < f

looking for '__gt__'
looking for '__coerce__'
looking for '__cmp__' ... Many thanks for your answer: you didn't just gave me the fish I asked but also
showed me how to use a net for catching other fish.
You're welcome! Python enjoys excellent "discoverabilit y" (a term
copiously illustrated, by explanation and by example, in Eric Raymond's
excellent book "The Art of Unix Programming", highly recommended in both
paper and free-on-the-net form) -- it shews enough of its workings,
easily enough, that it's well worth doing some sniffing around, and the
ability to hack together a 4-line class that displays things with some
print statements in an interactive session is a good example.

Of course, I _was_ being a tad too glib here, which helps explain...:
It seems I triggered a fierce debate with my question, but as far as I'm
concerned your example worked perfectly.


....the "debate", which was in fact quite friendly, even for this
community's pretty good standards. Summarizing, I half-cheated by using
an oldstyle class here, so that __getattr__ would indeed get called; a
newstyle class, while having just about the same behavior, does (...to
oversimply things a bit...) more processing at the time the class
statement is executed, it fills up a structure of internal 'slots', so
there is less "rooting around" at the time the < operator executes and
less of a chance to see the wheels in motion (there are of course plenty
of advantages in exchange, both conceptual and practical). Moreover the
'__coerce__' concept is being de-emphasized and deprecated, so the
"lookup" order shifts slightly (coercion is now tried only as a "last
ditch", after 3-way comparison with __cmp__ rather than before).

This doesn't mean you can't do "sniffing around" in newstyle classes,
but it may require a different tack, such as:
class foo(object): .... def __gt__(self, other):
.... print 'doing gt'
.... return NotImplemented
.... def __cmp__(self, other):
.... print 'doing cmp'
.... return NotImplemented
.... f=foo()
2<f doing gt
doing cmp
False


The "return NotImplemented" may be seen as a way to implement a specific
comparison (say __gt__) in some cases while punting to more generic ways
implicitly -- you may use it to indicate to Python "I don't know how to
do this specific comparison in this specific method, so please try
something else [along the usual orders in which things are tried]"...
Alex
Jul 18 '05 #10

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

Similar topics

2
2276
by: bq | last post by:
Hello, This post is really two questions. Question 1: What is the current status on a revision of ISO C++, specifically regarding plans for overloading composite operators? Some people in this group probably would know. By "overloading composite operators" I mean conversion of an expression like A = B * C; into a single function call (instead of three calls; one to "*", another to copy and another to "="). Here A, B and C are of a
20
1846
by: KL | last post by:
I am working on a school assignment, so please don't tell me the solution. I just want some direction. I am supposed to overload the >, <, ==, !=, >=, and <= operators using bool. I am having a bit of a problem in seeing what needs to happen here. I am just not sure how I do this. Will the overloading function recognize a < and a usual <? Do I do an IF (a.letters < b.letters){ return true }
5
3629
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: (), , ->, =. I wonder why there is such a restriction. Some tutorials say that 'new' and 'delete' can only be overloaded with static member functions, others say that all overloading function should be non-static. Then what is the fact, and why? ...
35
2070
by: josh | last post by:
Hi, I coded the following but It does not return what I expect, why? #include <iostream> using namespace std; class Other { public: int i;
3
1729
by: johnmmcparland | last post by:
Hi all, I know it is possible to overload the operators and < in C++ but how can I do this. Assume I have a class Date with three int members, m_day, m_month and m_year. In the .cpp files I have defined the < and operators; bool Date::operator<(const Date& d) {
15
1750
by: PengYu.UT | last post by:
Hi, It seems that C++ does not allow overloading operators for primative types, e.g. int, double. I'm wondering whether it is ture or there is some walk-around? Thanks, Peng #include <iostream>
8
2976
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, operator =, operator, operator(), and operator-must be nonstatic member function; this ensures that their first operands will be lvalues". I know that these operators must be nonstatic member functions, but why this ensure their first operands will...
7
1744
by: Rahul | last post by:
Hi Everyone, I was overloading the operator= function as a class member function, #include <iostream.h> class A { int value; public : A& operator = (const A& ref)
2
2949
by: jimzat | last post by:
I am trying to simulate the execution of some PLC ladder logic in python. I manually modified the rungs and executed this within python as a proof of concept, but I'd like to be able to skip the modification step. My thought was that this might be able to be completed via overloading, but I am not sure if (or how) it could be done. overloadings: + ==OR
0
9423
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10216
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10049
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9865
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8873
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7413
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5309
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3965
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3565
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.