operator overloading + - / * = etc...

S

Sybren Stuvel

SpreadTooThin enlightened us with:
Can these operators be overloaded?
Yes.

If so. How?

Implement __add__, __sub__ etc. in the class that you want to be able
to add, subtract, etc.

Sybren
 
T

Tim Chase

Can these operators be overloaded?

With the caveat of the "=" mentioned in the subject-line (being
different from "==")...I haven't found any way to override
assignment in the general case. There might be some oddball way
to do it via property() but AFAIK, this only applies to
properties of objects, not top-level names/variables. I'd love
to know if there's some workaround for this though...

-tkc
 
G

Georg Brandl

Tim said:
With the caveat of the "=" mentioned in the subject-line (being
different from "==")...I haven't found any way to override
assignment in the general case. There might be some oddball way
to do it via property() but AFAIK, this only applies to
properties of objects, not top-level names/variables. I'd love
to know if there's some workaround for this though...

In almost all cases, binding a name cannot be overridden.

There is a possibility to do that with globals, provided you do

exec code in globals_dict

where globals_dict is an instance of a subclass of dict that has a
customized __setitem__.

Georg
 
S

Sybren Stuvel

Tim Chase enlightened us with:
With the caveat of the "=" mentioned in the subject-line (being
different from "==")...I haven't found any way to override
assignment in the general case.

Why would you want to do that?

Sybren
 
T

Tim Chase

With the caveat of the "=" mentioned in the subject-line (being
Why would you want to do that?

For the same reason one would use property() to create
getter/setter functions for a particular variable--to intercept
attempts to set a variable. I'm not sure there's an elegant way
to do it other than creating a custom container object with a
getter/setter using property().

My purpose was just to note that the "=" assignment operator is
distinct from the remainder of the operators that you correctly
identified can be overridden with their associated __[operator]__
method.

-tkc
 
S

Steven D'Aprano

For the same reason one would use property() to create
getter/setter functions for a particular variable--to intercept
attempts to set a variable.

Despite sloppy talk to the contrary (which I think most of us do from time
to time), Python doesn't have variables. It has names and objects. Names
are just labels -- there is no difference in behavior between the *names*
this_is_an_integer and this_is_a_string. (The *objects* they point to are
a different story, naturally.)

Objects do not, and can not, know what names they are bound to, nor can
they tell when the name or names they are bound to changes. Objects just
don't care what names they are bound to -- in fact, many objects aren't
bound to any name at all.

Suppose we bind the name "x" to the object 1, and then rebind the name "x"
to the object []. Which object's hypothetical __assign__ method should get
called? Object 1 or object []? Both of them? In what order? Why should
the empty list care what names it is bound to?
I'm not sure there's an elegant way
to do it other than creating a custom container object with a
getter/setter using property().

You shouldn't be programming C++ in Python, you should rethink how you
are solving the problem.

But having done that, if you still find that the property() idiom makes
sense for names/objects, you can get close if you are willing to write x =
1 as NAMESPACE.x = 1, and then use a custom class or module to implement
the behavior you want.

Here is one module that you might be able to use:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207
 
S

Steve Holden

Tim said:
With the caveat of the "=" mentioned in the subject-line (being
different from "==")...I haven't found any way to override
assignment in the general case. There might be some oddball way
to do it via property() but AFAIK, this only applies to
properties of objects, not top-level names/variables. I'd love
to know if there's some workaround for this though...
That's because assignment isn't an operator - that's why (for example)

print x = 33

would be a syntax error. This is a deliberate design decision about
which, history shows, there is little use complaining.

regards
Steve
 
A

Antoon Pardon

Despite sloppy talk to the contrary (which I think most of us do from time
to time), Python doesn't have variables. It has names and objects. Names
are just labels -- there is no difference in behavior between the *names*
this_is_an_integer and this_is_a_string. (The *objects* they point to are
a different story, naturally.)

I honestly don't see why "variable" would be an inappropiate word to use.
AFAIU, python assignment seems to behave much like lisp and smalltalk
and I never heard that those communities found the word "variable"
inappropiate to use. And since the word variable originally comes
from mathematics and IMHO the mathematical semantics are closer
to the lisp/smalltalk/python semantics than the C/algol/pascal/ada
semantics I don't see why "variable" is seen as "sloppy talk"
 
B

Bruno Desthuilliers

Steven said:
For the same reason one would use property() to create
getter/setter functions for a particular variable--to intercept
attempts to set a variable.
(snip)

Suppose we bind the name "x" to the object 1, and then rebind the name "x"
to the object []. Which object's hypothetical __assign__ method should get
called?

The current namespace object, of course.
 
G

Georg Brandl

Bruno said:
Steven said:
With the caveat of the "=" mentioned in the subject-line (being
different from "==")...I haven't found any way to override
assignment in the general case.
Why would you want to do that?
For the same reason one would use property() to create
getter/setter functions for a particular variable--to intercept
attempts to set a variable.
(snip)

Suppose we bind the name "x" to the object 1, and then rebind the name "x"
to the object []. Which object's hypothetical __assign__ method should get
called?

The current namespace object, of course.

Which is?

Georg
 
T

Terry Reedy

Bruno Desthuilliers said:
The current namespace object, of course.

Implementing a namespace as a Python object (ie, dict) is completely
optional and implementation dependent. For CPython, the local namespace of
a function is generally *not* done that way.

tjr
 
T

Theerasak Photha

I honestly don't see why "variable" would be an inappropiate word to use.
AFAIU, python assignment seems to behave much like lisp and smalltalk
and I never heard that those communities found the word "variable"
inappropiate to use. And since the word variable originally comes
from mathematics and IMHO the mathematical semantics are closer
to the lisp/smalltalk/python semantics than the C/algol/pascal/ada
semantics I don't see why "variable" is seen as "sloppy talk"

Um, that's what I usually use anyway... :)

-- Theerasak
 
F

Fredrik Lundh

Roman said:
People who complain often fail to see how

x = foo()
while x:
process(x)
x = foo()

is safer than

while x = foo():
process(x)

that's spelled:

for x in foo():
process(x)

in Python, or, if foo() just refuses be turned into a well-behaved Python
citizen:

while 1:
x = foo()
if not x:
break
process(x)

(this is the standard "loop-and-a-half" pydiom, and every python pro-
grammer should be able to identify it as such in a fraction of a second).

or for the perhaps-overly-clever hackers,

for x in iter(lambda: foo() or None, None):
process(x)

it's not like the lack of assignment-as-expression is forcing anyone to
duplicate code in today's Python.

also, in my experience, most assignment-as-expression mistakes are done
in if-statements, not while-statements (if not else because if statements are
a lot more common in most code). the "but it cuts down on duplication"
argument doesn't really apply to if-statements.

</F>
 
P

Paul Rubin

Fredrik Lundh said:
or for the perhaps-overly-clever hackers,

for x in iter(lambda: foo() or None, None):
process(x)

for x in takewhile(foo() for _ in repeat(None)):
process (x)
 
P

Paul Rubin

Fredrik Lundh said:
or for the perhaps-overly-clever hackers,

for x in iter(lambda: foo() or None, None):
process(x)

for x in takewhile(bool, (foo() for _ in repeat(None))):
process(x)

Meh, both are ugly.
 
A

Antoon Pardon

for x in takewhile(foo() for _ in repeat(None)):
process (x)
.... print x
....
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: takewhile expected 2 arguments, got 1
 
A

Antoon Pardon

for x in takewhile(bool, (foo() for _ in repeat(None))):
process(x)

Meh, both are ugly.

Sure, but so is IMO the current pythonic idiom.

Suppose one has the following intention in mind:

while x = setup():
if y = pre_process() in ErrorCondition:
break
post_process(y)
else:
NormalTermination()

The pythonic idiom for this case would then be something like:

while 1:
x = setup()
if x:
NormalTermination()
break
y = pre_process(x)
if y in ErrorCondition:
break
post_process(y)

There was some time it seemed PEP: 315 would be implemented so
that this could have been written as:

do:
x = setup()
while x:
y = pre_process(x)
if y in ErrorCondition:
break
post_process(y)
else:
NormalTermination()


Which IMO would have been clearer. Alas PEP 315 is deffered so
it will be probably a long time before this will be implemented.
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top