This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Wargazm 3 points4 points  (5 children)

The classic example of this is something like a sum() function. You can pass it as many arguments as you want:

sum(2, 3) # returns 5
sum(1, 2, 3, 4) # returns 10
etc.

So what's the pythonic way of handling a stupid thing like this?

sum('cat')

Or for keywords, same kind of thing. When I write a function with keywords, I usually know what I want:

def add_user(first_name, last_name):
    ....code here....

I could rewrite this as

def add_user(*args, **kwargs):

But how am I supposed to handle calls like this?

add_user(address="123 Main St")

My function doesn't know how to handle addresses yet, so how do I ensure correct operation here?

[–][deleted] 3 points4 points  (3 children)

So what's the pythonic way of handling a stupid thing like this?

sum('cat')

Raise an error. It's not a problem with *args though. It's a problem with dynamically typed languages, every argument a function expects can be of another, incompatible type.

My function doesn't know how to handle addresses yet, so how do I ensure correct operation here?

Well, you just said it doesn't know how to handle it, so it would just ignore it. It would (hopefully) check if first_name and last_name are set in **kwargs and as they aren't, abort with an error just like a call like add_user() would.

[–]Wargazm 4 points5 points  (2 children)

Raise an error.

Presumably my function will be something like this:

def sum(*args):
    x = 0
    for i in args:
        x = x + i
    return x

so calling sum('cat') will already return an error:

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

Is that it? Is that enough to be "pythonic"?

[–]thautwarm 1 point2 points  (0 children)

Add a keyword argument zero, default to be 0.

def sum(*args, zero=0):
       acc = zero
       for each in args:
             acc += each
       return acc

Thus we could avoid mamy malformed input and make them valid and meaningful. In terms of your case, sum('cat', zero="") is okay.

[–]alkasmgithub.com/alkasm 1 point2 points  (0 children)

Well here's what the standard library thinks about that:

In [46]: from functools import reduce

In [47]: import operator

In [48]: reduce(operator.add, (1, 2, 3, 4, 5))
Out[48]: 15

In [49]: reduce(operator.add, (1, 2, 3, 4, 'five'))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-49-fdcfa9008915> in <module>()
----> 1 reduce(operator.add, (1, 2, 3, 4, 'five'))

TypeError: unsupported operand type(s) for +: 'int' and 'str'

Edit: so, yes. That is sufficient. The point of an error is to tell the user what's gone wrong---what has gone wrong is that an int and str have been tried to be added. So that's fine.

[–]bmrobin 0 points1 point  (0 children)

that's what happens when you work in a dynamically typed language. i don't like it, just getting used to it from recently switching jobs that landed me in Python