any way to customize the is operator?

L

Lonnie Princehouse

There doesn't seem to be any way to customize the behavior of "is" as
can be done for other operators... why not?
 
F

Fredrik Lundh

Lonnie said:
There doesn't seem to be any way to customize the behavior of "is" as
can be done for other operators... why not?

because it does "id(a) == id(b)", and there's no way to customize
the behaviour of id().

(objects are not allowed to lie about who they are, or what they
are).

</F>
 
L

Lonnie Princehouse

(objects are not allowed to lie about who they are, or what they are).

Dangit! I need to find a less honest programming language. Anyone
have a Perl cookbook handy? ...
 
B

bruno at modulix

Lonnie said:
Dangit! I need to find a less honest programming language. Anyone
have a Perl cookbook handy? ...

+1 QOTW (approved by a fellow Perl programmer FWIW !-)
 
S

Sybren Stuvel

Lonnie Princehouse enlightened us with:
There doesn't seem to be any way to customize the behavior of "is" as
can be done for other operators... why not?

Pure logic: A == A or A != A. An object is another object or not.
Why would you want to change that?

Sybren
 
S

Steven D'Aprano

Dangit! I need to find a less honest programming language. Anyone
have a Perl cookbook handy? ...

No, you need a better algorithm.


Why did you want to customize "is"?
 
L

Lonnie Princehouse

Why did you want to customize "is"?

Well, mostly out of principle ;-)

But also because I'm wrapping a C library which passes around C structs
which are wrapped in shim C++ classes for a Boost.Python layer. Boost
Python does a marvelous job of translating between Python and C++ data
types; when a C structure is returned, it magically translates that
structure into a Python wrapper. The problem is that a _new_ Python
wrapper is created every time a pointer is returned, even if a wrapper
already exists for that particular pointer.

To illustrate: Suppose you have a function in C++ which is a simple
identity function, e.g.

template <typename T>
T *identity (T *x) {
return x;
}

Calling the wrapped version of this function from Python will produce a
Python wrapper which represents the same underlying C++ object, but is
not actually the same Python object:
False

I wanted to override the behavior of "is" so that (a is b) would be
True --- which shouldn't have caused a problem, since the wrapper
class's attributes are read-only from Python. As it is, I've overriden
__cmp__ and __hash__, so at least I get the correct dictionary behavior
True

It's quite possible that there is some way to do this correctly from
the Boost.Python side of things... my understanding of how to use
Boost.Python is minimal.
 
S

Steve Holden

Lonnie said:
Well, mostly out of principle ;-)

But also because I'm wrapping a C library which passes around C structs
which are wrapped in shim C++ classes for a Boost.Python layer. Boost
Python does a marvelous job of translating between Python and C++ data
types; when a C structure is returned, it magically translates that
structure into a Python wrapper. The problem is that a _new_ Python
wrapper is created every time a pointer is returned, even if a wrapper
already exists for that particular pointer.

To illustrate: Suppose you have a function in C++ which is a simple
identity function, e.g.

template <typename T>
T *identity (T *x) {
return x;
}

Calling the wrapped version of this function from Python will produce a
Python wrapper which represents the same underlying C++ object, but is
not actually the same Python object:



False

I wanted to override the behavior of "is" so that (a is b) would be
True --- which shouldn't have caused a problem, since the wrapper
class's attributes are read-only from Python. As it is, I've overriden
__cmp__ and __hash__, so at least I get the correct dictionary behavior



True

It's quite possible that there is some way to do this correctly from
the Boost.Python side of things... my understanding of how to use
Boost.Python is minimal.
I will adopt my usual stance here of unequivocally stating that there is
no way you can do what you want to. In the case of the "is" operator you
can only expect truth when the left- and right-hand side operands refer
to the same object.

This strategy is usually sound: typically, before the metaphorical ink
has dried on my post some upstart comes along to prove me completely
wrong. So, I have done about all I can to help you. It's up to the rest
of the community now to prove me wrong (as they have so many times in
the past :).

regards
Steve

PS: I'm afraid I couldn't resisit shortening yur odds somewhat by doing
what I usually fail to do and examining the source of is_() in
Modules/operator.c. I'm afraid it's not looking good ... the result of
"is" does appear to depend only on the memory addresses of the two
operands being the same:

result = (a1 == a2) ? Py_True : Py_False;
Py_INCREF(result);

sorry ...
 
A

Aahz

Well, mostly out of principle ;-)

But also because I'm wrapping a C library which passes around C structs
which are wrapped in shim C++ classes for a Boost.Python layer. Boost
Python does a marvelous job of translating between Python and C++ data
types; when a C structure is returned, it magically translates that
structure into a Python wrapper. The problem is that a _new_ Python
wrapper is created every time a pointer is returned, even if a wrapper
already exists for that particular pointer.

Then you need to fix Boost.Python. This cannot and will not get fixed at
the Python level -- how can Python possibly know that they are the same
objects?
 
T

Terry Reedy

What I think you need is a custom version of the .__eq__ (self,other)
method that pierces thru the wrappers to compare the underlying C++
objects. Then test a == b.

In Python, 'is' specifically means identity of Python objects.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,522
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top