Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > sum() requires number, not simply __add__

Reply
Thread Tools

sum() requires number, not simply __add__

 
 
Ian Kelly
Guest
Posts: n/a
 
      02-23-2012
On Thu, Feb 23, 2012 at 2:53 PM, Chris Angelico <(E-Mail Removed)> wrote:
> On Fri, Feb 24, 2012 at 8:41 AM, Arnaud Delobelle <(E-Mail Removed)> wrote:
>> _sentinel = object()
>>
>> def sum(iterable, start=_sentinel):
>> * *if start is _sentinel:
>>
>> del _sentinel

>
> Somewhat off-topic: Doesn't the if statement there do a lookup for a
> global, which would mean that 'del _sentinel' will cause it to fail?
> Or have I missed something here?


I believe you're correct. If you really want to delete the _sentinel
reference though, you could do:

def sum(iterable, start=object()):
if start is sum.func_defaults[0]:
...

Cheers,
Ian
 
Reply With Quote
 
 
 
 
Chris Angelico
Guest
Posts: n/a
 
      02-23-2012
On Fri, Feb 24, 2012 at 8:59 AM, Arnaud Delobelle <(E-Mail Removed)> wrote:
> def sum(iterable, start=_sentinel, _sentinel=_sentinel):


Is this a reason for Python to introduce a new syntax, such as:

def foo(blah, optional=del):
if optional is del: print("No argument was provided")

Basically, 'del' is treated like a unique non-providable object, only
possible in an argument list and only if the argument was omitted. No
more proliferation of individual sentinels... what do you think?

(I picked "del" because it's an existing keyword. Fairly arbitrary
choice though.)

Chris Angelico
 
Reply With Quote
 
 
 
 
Steven D'Aprano
Guest
Posts: n/a
 
      02-23-2012
On Fri, 24 Feb 2012 08:53:49 +1100, Chris Angelico wrote:

> On Fri, Feb 24, 2012 at 8:41 AM, Arnaud Delobelle <(E-Mail Removed)>
> wrote:
>> _sentinel = object()
>>
>> def sum(iterable, start=_sentinel):
>> * *if start is _sentinel:
>>
>> del _sentinel

>
> Somewhat off-topic: Doesn't the if statement there do a lookup for a
> global, which would mean that 'del _sentinel' will cause it to fail? Or
> have I missed something here?


Yes, deleting _sentinel will cause the custom sum to fail, and yes, you
have missed something.

If the caller wants to mess with your library and break it, they have
many, many ways to do so apart from deleting your private variables.


del _sentinel
_sentinel = "something else"
sum.__defaults__ = (42,) # mess with the function defaults
sum.__code__ = (lambda a, b=None: 100).__code__ # and with func internals
sum = None # change your custom sum to something else
del sum # or just delete it completely
len = 42 # shadow a built-in
import builtins; del builtins.range # really screw with you


If your application stops working after you carelessly mess with
components your application relies on, the right answer is usually:

"Don't do that then."

Python doesn't try to prevent people from shooting themselves in the foot.


Monkey-patching-by-actual-monkeys-for-fun-and-profit-ly y'rs,


--
Steven
 
Reply With Quote
 
Chris Angelico
Guest
Posts: n/a
 
      02-23-2012
On Fri, Feb 24, 2012 at 10:33 AM, Steven D'Aprano
<(E-Mail Removed)> wrote:
> Yes, deleting _sentinel will cause the custom sum to fail, and yes, you
> have missed something.
>
> If the caller wants to mess with your library and break it, they have
> many, many ways to do so apart from deleting your private variables.


I was looking at the module breaking itself, though, not even waiting
for the caller to do it.

ChrisA
 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      02-24-2012
Buck Golemon wrote:

> I feel like the design of sum() is inconsistent with other language
> features of python. Often python doesn't require a specific type, only
> that the type implement certain methods.
>
> Given a class that implements __add__ why should sum() not be able to
> operate on that class?
>
> We can fix this in a backward-compatible way, I believe.
>
> Demonstration:
> I'd expect these two error messages to be identical, but they are
> not.
>
> >>> class C(object): pass
> >>> c = C()
> >>> sum((c,c))

> TypeError: unsupported operand type(s) for +: 'int' and 'C'
> >>> c + c

> TypeError: unsupported operand type(s) for +: 'C' and 'C'


You could explicitly provide a null object:

>>> class Null(object):

.... def __add__(self, other):
.... return other
....
>>> null = Null()
>>> class A(object):

.... def __init__(self, v):
.... self.v = v
.... def __add__(self, other):
.... return A("%s+%s" % (self, other))
.... def __str__(self):
.... return self.v
.... def __repr__(self):
.... return "A(%r)" % self. v
....
>>> sum(map(A, "abc"))

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'A'
>>> sum(map(A, "abc"), null)

A('a+b+c')


 
Reply With Quote
 
Antoon Pardon
Guest
Posts: n/a
 
      02-24-2012
On 02/24/2012 12:33 AM, Steven D'Aprano wrote:
> If your application stops working after you carelessly mess with
> components your application relies on, the right answer is usually:
>
> "Don't do that then."
>
> Python doesn't try to prevent people from shooting themselves in the foot.
>

Yes it does! A simple example is None as a keyword to prevent
assignments to it.

--
Antoon Pardon
 
Reply With Quote
 
Roy Smith
Guest
Posts: n/a
 
      02-24-2012
In article <(E-Mail Removed)>,
Antoon Pardon <(E-Mail Removed)> wrote:

> > Python doesn't try to prevent people from shooting themselves in the foot.
> >

> Yes it does! A simple example is None as a keyword to prevent
> assignments to it.


Hmmm. Just playing around with some bizarre things to do with None, and
discovered this:

>>> import sys as None


doesn't give an error, but also doesn't assign the module to the symbol
'None'. Weird.
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      02-24-2012
On 2/24/2012 8:23 AM, Roy Smith wrote:
> In article<(E-Mail Removed)>,
> Antoon Pardon<(E-Mail Removed)> wrote:
>
>>> Python doesn't try to prevent people from shooting themselves in the foot.
>>>

>> Yes it does! A simple example is None as a keyword to prevent
>> assignments to it.

>
> Hmmm. Just playing around with some bizarre things to do with None, and
> discovered this:
>
>>>> import sys as None

>
> doesn't give an error, but also doesn't assign the module to the symbol
> 'None'. Weird.


In 3.2
>>> import sys as None

SyntaxError: invalid syntax

--
Terry Jan Reedy

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Don't work __getattr__ with __add__ Андрей Симурзин Python 2 03-04-2010 08:54 AM
proxy class and __add__ method Magnus Schuster Python 0 07-29-2008 04:13 PM
simply tag just not applying... :o shawnews HTML 2 11-24-2006 01:04 AM
Difference: __iadd__ and __add__ Ronny Mandal Python 3 02-18-2006 02:47 PM
ASP:Button on_click event simply will not ever fire Weston Weems ASP .Net 2 09-03-2004 06:14 PM



Advertisments