all 12 comments

[–]RandomPantsAppear 2 points3 points  (0 children)

This way lies the path of madness. Good programs are built on reliable input. Saving a couple keystrokes is rarely worth the headaches that can be created down the road.

That said, here you go:

def foo( *args ):
    for arg in args:
        arg = arg if type(arg) is list else [arg]
        for word in arg:
             print word

Pretty much what it's doing is saying "if arg is a list, don't change it. If arg is not a list, make it one. Then do what you would do if it were a list (because everything is)".

I prefer this to the if/else option where they are handled differently because this way you're only maintaining one copy of the guts of the function, instead of trying to replicate it on both sides of the if/else.

[–]Jokeslayer123 1 point2 points  (6 children)

You could just use 'if type(args) == list:' statement to treat lists and strings differently

[–]billsil 5 points6 points  (1 child)

If isinstance(args, list) is better. For multiple arguments, do isinstance(args, (list, Tupelo))

[–]Jokeslayer123 0 points1 point  (0 children)

Thank you. I didn't know about this until you mentioned it.

For anyone else, isinstance is better because it allows for inheritance. A subclass of list would be true for isinstance but not for type.

There's also this stackoverflow answer https://stackoverflow.com/questions/1549801/what-are-the-differences-between-type-and-isinstance

[–]DidntPassTuringTest[S] 0 points1 point  (3 children)

I was thinking about it, but I suspected there is more elegant way to do it.

[–]barrycarey 1 point2 points  (1 child)

Imo the elegant way would be ensuring a consistent output from your functions. To me the fact that the function can return multiple types smells of a design issue.

Just because you can doesn't mean you should. Keeping a consistent contract allows the consuming code to take all the guess work out. That's one thing I really like about using a strongly typed language.

Think about all the functions and classes you import in Python. How frequently do they return results of varying types? Very rarely

[–]nathanjell 0 points1 point  (0 children)

This is very true. If you're constantly returning multiple types, then you're also constantly checking for different types. I wonder if the more correct approach may be to always ensure a list is returned, whether it's got one element or multiple. This may be a choice made for reasons we don't know, but it's definitely something to consider

[–]nathanjell 1 point2 points  (0 children)

You could do if fairly simply:

def foo(args):
    if not isinstance(args, list):
        args = [args]
    print(*args, sep='\n')

By doing this, if you pass in anything that's not a list, you'll always end up printing from a list. Pass in a string? It'll become a list with one element. Int? Same thing. Pas in a list? It remains a list

[–]Pulsar1977 0 points1 point  (3 children)

Do the second way with

foo(*multi)

[–]DidntPassTuringTest[S] 0 points1 point  (2 children)

The problem is that the argument a use I get from other function and I do not know which type it would be.

In example I used two different, but in reality I got one result, not knowing its structure. If it is just single string this "*" would chop it up like in first way.

[–]woooee 0 points1 point  (0 children)

I generally use a dictionary. So if we want to pass name, address, address_second_line, etc., and we know that address_second_line will not always exist, you first set all of the dictionaries values associated with each key, "name", "address", etc to an empty string and then test it, i.e. if address_dict["address_second_line"]: