Posts: 4,647
Threads: 1,494
Joined: Sep 2016
Jan-10-2020, 12:45 AM
(This post was last modified: Jan-10-2020, 12:45 AM by Skaperen.)
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?
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 419
Threads: 34
Joined: May 2019
Jan-10-2020, 05:13 AM
(This post was last modified: Jan-10-2020, 05:13 AM by michael1789.)
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/
Posts: 8,160
Threads: 160
Joined: Sep 2016
Jan-10-2020, 08:12 AM
(This post was last modified: Jan-10-2020, 08:12 AM by buran.)
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.
Posts: 4,647
Threads: 1,494
Joined: Sep 2016
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.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 8,160
Threads: 160
Joined: Sep 2016
Jan-10-2020, 08:32 AM
(This post was last modified: Jan-10-2020, 08:32 AM by buran.)
(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.
Posts: 7,319
Threads: 123
Joined: Sep 2016
Jan-10-2020, 12:13 PM
(This post was last modified: Jan-10-2020, 12:13 PM by snippsat.)
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)
Posts: 4,647
Threads: 1,494
Joined: Sep 2016
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.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
|