Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 pass value to function with * and/or **
#1
if i define a function like:
def foo(*boo,**hoo):
    ...
    return (boo,hoo)
then call it while passing a created type that operates like a list or dictionary, will these values in the function (e.g. boo and hoo in the above code) have the types as passed or will they be converted to list or dictionary, as appropriate?
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Quote
#2
The code in the function needs to be able to handle the type of what you give it, but that code can include a type check and act accordingly. As for converting types as appropriate, that's not automatic, you will have to write that code.

I don't really know the specifics of it all but this page seem to explain it all better than I can: geeksforgeeks_DOT_org/type-isinstance-python/
Quote
#3
I think there is misunderstanding.
boo will be a tuple, hoo will be a dict.
if you call the function with [something like] list or dict you either unpack it during the call (in effect passing individual elements) or you will end up with 2 arguments in boo tuple and empty dict:
def foo(*boo, **hoo):
    print(type(boo), boo)
    print(type(hoo), hoo)

spam = [1, 2]
eggs = {'a':3, 'b':4}

foo(*spam, **eggs)
foo(spam, eggs)
foo(5, 6, c=7, d=8)
Output:
<class 'tuple'> (1, 2) <class 'dict'> {'a': 3, 'b': 4} <class 'tuple'> ([1, 2], {'a': 3, 'b': 4}) <class 'dict'> {} <class 'tuple'> (5, 6) <class 'dict'> {'c': 7, 'd': 8}
the idea is to allow having variable number of positional (*args) or keyword (**kwargs) arguments. *args and **kwargs is conventional way to name these.
snippsat and perfringo like this post
Quote
#4
normally, when the caller is not using * or **, but the function is defined with * or **, they are tuple and dictionary. what i am wondering is, if the caller does use * and/or **, does what the caller provides get passed through to the function as-is, or does it go through the argument handling mechanisms that give the function a tuple and dictionary. maybe the mechanism of setting up the call uses what is provided with * and ** and sets up a function call like any other call, then it all gets unwound (to a tuple and/or dictionary) as the function sets up to run. it comes down to how function calls are implemented unless this is defined somewhere (i haven't seen it). other Python implementations could do this different than how CPython does it, if it's not defined.
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Quote
#5
(Jan-10-2020, 08:19 AM)Skaperen Wrote: if the caller does use * and/or **, does what the caller provides get passed through to the function as-is, or does it go through the argument handling mechanisms that give the function a tuple and dictionary
I think I show all possible variations in my example. You can do the same with your own type/class objects and see what the result is. Here it is again

from collections import OrderedDict

def foo(*boo, **hoo):
    print(type(boo), boo)
    print(type(hoo), hoo)
 
spam = [1, 2]
eggs = OrderedDict((('a', 3), ('b', 4)))
 
foo(*spam, **eggs)
foo(spam, eggs)
foo(5, 6, c=7, d=8)
Output:
<class 'tuple'> (1, 2) <class 'dict'> {'a': 3, 'b': 4} <class 'tuple'> ([1, 2], OrderedDict([('a', 3), ('b', 4)])) <class 'dict'> {} <class 'tuple'> (5, 6) <class 'dict'> {'c': 7, 'd': 8}
as you can see that when unpacked elements of the list are stored in a tuple and elements of the OrderedDict are stored in a dict
when not unpacked you get list and OrderedDict as elements in a tuple.
bottom line - args/boo will be a tuple always, kwargs/hoo will be a dict always.
snippsat likes this post
Quote
#6
I think @buran explanation is good,some addition info that use type hints.
For the user of function it's most important what should be passed in,
not how the creator of function handle arguments from tuple(*args) or dict(**kwargs).
Type annotations give a hint of what's wanted in as arguments in without any documentation(as it should also be).
def foo(*boo: int, **hoo: str):
    print(sum(boo), type(boo))
    print(hoo, type(hoo))

foo(1, 2, 3, 4)
print('-'*15)
foo(a='car', b='Taxi')
Output:
10 <class 'tuple'> {} <class 'dict'> --------------- 0 <class 'tuple'> {'a': 'car', 'b': 'Taxi'} <class 'dict'>
Type hints by themselves don’t cause Python to enforce types,so will give error(TypeError) in sum() if give a string.
def foo(*boo: int, **hoo: str):
    print(sum(boo), type(boo))
    print(hoo, type(hoo))

foo('car', 2, 99)
Output:
Traceback (most recent call last): File "code_type1.py", line 5, in <module> foo('car', 2, 99) File "code_type1.py", line 2, in foo print(sum(boo), type(boo)) TypeError: unsupported operand type(s) for +: 'int' and 'str
Have to use a static type checker like Mypy,to catch error earlier.
Output:
E:\div_code λ mypy code_type1.py code_type1.py:5: error: Argument 1 to "foo" has incompatible type "str"; expected "int" Found 1 error in 1 file (checked 1 source file)
buran likes this post
Quote
#7
so, i can safely assume i'll get a (possibly empty) tuple and/or dictionary in such a function, no matter how it gets called.
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Quote

Top Page

Forum Jump:


Users browsing this thread: 1 Guest(s)