Default array parameters python - python-3.x

I need to understand why the calls to this function amends to the array which got a default initialization in the function declaration? Appreciate if any reference to the API specs
def f(i, values = []):
values.append(i)
print(values)
return values
Calls to:
f(1) prints -> [1]
f(2) prints -> [1, 2]
f(3) prints -> [1, 2, 3]
and so one

Related

How to multiply 2 input lists in python

Please help me understand how to code the following task in Python using input
Programming challenge description:
Write a short Python program that takes two arrays a and b of length n
storing int values, and returns the dot product of a and b. That is, it returns
an array c of length n such that c[i] = a[i] · b[i], for i = 0,...,n−1.
Test Input:
List1's input ==> 1 2 3
List2's input ==> 2 3 4
Expected Output: 2 6 12
Note that the dot product is defined in mathematics to be the sum of the elements of the vector c you want to build.
That said, here is a possibiliy using zip:
c = [x * y for x, y in zip(a, b)]
And the mathematical dot product would be:
sum(x * y for x, y in zip(a, b))
If the lists are read from the keyboard, they will be read as string, you have to convert them before applying the code above.
For instance:
a = [int(s) for s in input().split(",")]
b = [int(s) for s in input().split(",")]
c = [x * y for x, y in zip(a, b)]
Using for loops and appending
list_c = []
for a, b in zip(list_a, list_b):
list_c.append(a*b)
And now the same, but in the more compact list comprehension syntax
list_c = [a*b for a, b in zip(list_a, list_b)]
From iPython
>>> list_a = [1, 2, 3]
>>> list_b = [2, 3, 4]
>>> list_c = [a*b for a, b in zip(list_a, list_b)]
>>> list_c
[2, 6, 12]
The zip function packs the lists together, element-by-element:
>>> list(zip(list_a, list_b))
[(1, 2), (2, 3), (3, 4)]
And we use tuple unpacking to access the elements of each tuple.
From fetching the input and using map & lambda functions to provide the result. If you may want to print the result with spaces between (not as list), use the last line
list1, list2 = [], []
list1 = list(map(int, input().rstrip().split()))
list2 = list(map(int, input().rstrip().split()))
result_list = list(map(lambda x,y : x*y, list1, list2))
print(*result_list)
I came out with two solutions. Both or them are the ones that are expected in a Python introductory course:
#OPTION 1: We use the concatenation operator between lists.
def dot_product_noappend(list_a, list_b):
list_c = []
for i in range(len(list_a)):
list_c = list_c + [list_a[i]*list_b[i]]
return list_c
print(dot_product_noappend([1,2,3],[4,5,6])) #FUNCTION CALL TO SEE RESULT ON SCREEN
#OPTION 2: we use the append method
def dot_product_append(list_a, list_b):
list_c = []
for i in range(len(list_a)):
list_c.append(list_a[i]*list_b[i])
return list_c
print(dot_product_append([1,2,3],[4,5,6])) #FUNCTION CALL TO SEE RESULT ON SCREEN
Just note that the first method requires that you cast the product of integers to be a list before you can concatenate it to list_c. You do that by using braces ([[list_a[i]*list_b[i]] instead of list_a[i]*list_b[i]). Also note that braces are not necessary in the last method, because the append method does not require to pass a list as parameter.
I have added the two function calls with the values you provided, for you to see that it returns the correct result. Choose whatever function you like the most.

Using map python with key argument

I have a function that looks like this:
def myFunct(arg1=None,arg2=None,arg3=None):
pass
I would like to use that function with a map function but with argument 1 and 3 only.
idea would be:
map(myFunct,list_arg1,list_arg3)
so each of the call would be myFunct(value1,arg3=value3)
How could I achieve that ?
You could use lambda to map the arguments to your keyword arguments.
def foo(arg1=None, arg2=None, arg3=None):
return arg1 + arg3
list1 = [3, 4, 5]
list2 = [5, 6, 7]
print(list(map(lambda x, y: foo(arg1=x, arg3=y), list1, list2)))
Another approach is to keep your function as is and modify what you are mapping over:
from itertools import repeat
def f(x = 0, y = 0, z = 0):
return sum((x,y,z))
map(f,range(1,10),repeat(0),range(21,30))
Although from a readability point of view, a simple generator expression might be preferable to any solution based on map, something along the lines of:
f(x = i,z = j) for i,j in zip(range(1,10),range(21,30)))

Python splat-in-the-middle

You can put splat arguments in the middle rather than at the end (only in python 3 it seems):
import functools
def wierd_sum(use_str_cat=False, *args, use_product=False):
if use_str_cat:
return ''.join([str(a) for a in args])
elif use_product:
return functools.reduce(lambda a,b : a*b, args)
else:
return functools.reduce(lambda a,b : a+b, args)
Now how do you use said function?
print(wierd_sum(1, 2, 3)) # 23 -> Concatenation, 1 counts as True.
print(wierd_sum(False, 2, 3, 4, 5, True)) # 15 -> Addition, True counts as 1.
print(wierd_sum(False, 2, 3, 4, 5, use_product=True)) # 120 -> Multiplication 2*3*4*5
print(wierd_sum(use_str_cat=True, 1, 2, 3)) # SyntaxError: positional argument follows keyword argument.
print(wierd_sum(1, 2, 3, use_str_cat=False)) # TypeError: wierd_sum() got multiple values for argument 'use_str_cat'
My question is, is there ever, ever, EVER a reason to do such a thing?
This is to allow for keyword only arguments; similar to positional-only arguments (comparison here).
Ideally though, unless you actually need the varargs, you should omit the name to disallow varargs from being supplied:
def my_func(a, *, keyword_only=True):
pass
my_func(1, 2) # TypeError: my_func() takes 1 positional argument but 2 were given
my_func(1, keyword_only=2) # Fine

How to get element from iterator object?

can anyone try to explain to me how the following code work? As I understand, unpack is like a, b, i = [1,2,3] but how the following code work to get x? I have try to debug if I have x = iter(collections.deque([1,2,3,4,5], maxlen=1))
<_collections._deque_iterator object at 0x01239>
import collections
x, = iter(collections.deque([1,2,3,4,5], maxlen=1))
Here's a simpler example
>>> x = [24]
>>> x
[24]
>>> x, = [24]
>>> x
24
>>> x, y = [24, 96]
>>> x
24
>>> y
96
It's equivalent to your example since if you do list(iter(collections.deque([1,2,3,4,5], maxlen=1))) it's just a list with one element, [5].
You're correct that this is doing unpacking. You could write it as (x,) so that it looks more like a tuple if just x, is confusing. The comma after x makes x refer to the first element of a tuple with one element.
Your code above produces x=5 for me, not an iterator object.
Usually with an iterator object, (like a generator) use of the next() works
Here's a short example with the fibonacci sequence. Using the yield produces a generator object.
def iterative_fib(n):
a,b = 0,1
i=1
while i<n:
a, b = b, a+b
# print(b)
i+=1
yield b
x = iterative_fib(50)
next(x) # 12586269025
I'm not 100% sure specifically in your case, but try using next because next expects an iterator. If this doesn't work, then maybe produce a code example that replicates your issue.
Docs for next() : https://docs.python.org/3/library/functions.html#next
Edit:
Seeing some other answers regarding unpacking lists, here are some other ways using *:
a = [1,2,3,4,5]
a,b,c,d,e = [1,2,3,4,5] # you already mentioned this one
a, *b = [1,2,3,4,5] # a =[1], b=[2, 3, 4, 5]
a, *b, c, d = [1,2,3,4,5] #a =[1], b=[2,3], c=[4], d=[5]
*a, b, c = [1,2,3,4,5] # a=[1,2,3], b=[4], c=[5]
#But this wont work:
a, *b, *c = [1,2,3,4,5] # SyntaxError: two starred expressions in assignment

Python looping assignment

We just started learning about loops and one of my tasks is to
def multiples(n,xs):
Given an integer n and a list of integers xs, check and return values from
xs that are multiples of n as a list, preserving the occurrence order from xs.
Restriction: Do NOT modify the incoming list xs: build up a new list to return.
Examples:
multiples(2,[1,2,3,4,5,6]) → [2,4,6]
multiples(5,[5,10,5,10]) → [5,10,5,10] #keep duplicates
multiples(3,[11,13]) → []
Could anyone help on how to start/solve out this problem?
You can try below function -
def multiples(n,xs):
return filter(lambda x: not x%n, xs)
>>> multiples(2,[1,2,3,4,5,6])
[2, 4, 6]
>>> multiples(5,[5,10,5,10])
[5, 10, 5, 10]
>>> multiples(3,[11,13])
[]
From doc
filter(function, iterable) - Construct a list from those elements of iterable for which function returns true.

Resources