What is returned after using *[] [duplicate] - python

This question already has answers here:
What do the * (star) and ** (double star) operators mean in a function call?
(4 answers)
Closed 2 years ago.
I'm using itertools.chain to "flatten" a list of lists in this fashion:
uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))
how is this different than saying:
uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

* is the "splat" operator: It takes an iterable like a list as input, and expands it into actual positional arguments in the function call.
So if uniqueCrossTabs were [[1, 2], [3, 4]], then itertools.chain(*uniqueCrossTabs) is the same as saying itertools.chain([1, 2], [3, 4])
This is obviously different from passing in just uniqueCrossTabs. In your case, you have a list of lists that you wish to flatten; what itertools.chain() does is return an iterator over the concatenation of all the positional arguments you pass to it, where each positional argument is iterable in its own right.
In other words, you want to pass each list in uniqueCrossTabs as an argument to chain(), which will chain them together, but you don't have the lists in separate variables, so you use the * operator to expand the list of lists into several list arguments.
chain.from_iterable() is better-suited for this operation, as it assumes a single iterable of iterables to begin with. Your code then becomes simply:
uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))

It splits the sequence into separate arguments for the function call.
>>> def foo(a, b=None, c=None):
... print a, b, c
...
>>> foo([1, 2, 3])
[1, 2, 3] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
... print a
...
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)

Just an alternative way of explaining the concept/using it.
import random
def arbitrary():
return [x for x in range(1, random.randint(3,10))]
a, b, *rest = arbitrary()
# a = 1
# b = 2
# rest = [3,4,5]

Related

What does * mean in front of self.dictionary.values() in a class in Python? [duplicate]

This question already has answers here:
What do the * (star) and ** (double star) operators mean in a function call?
(4 answers)
Closed 2 years ago.
I'm using itertools.chain to "flatten" a list of lists in this fashion:
uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))
how is this different than saying:
uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))
* is the "splat" operator: It takes an iterable like a list as input, and expands it into actual positional arguments in the function call.
So if uniqueCrossTabs were [[1, 2], [3, 4]], then itertools.chain(*uniqueCrossTabs) is the same as saying itertools.chain([1, 2], [3, 4])
This is obviously different from passing in just uniqueCrossTabs. In your case, you have a list of lists that you wish to flatten; what itertools.chain() does is return an iterator over the concatenation of all the positional arguments you pass to it, where each positional argument is iterable in its own right.
In other words, you want to pass each list in uniqueCrossTabs as an argument to chain(), which will chain them together, but you don't have the lists in separate variables, so you use the * operator to expand the list of lists into several list arguments.
chain.from_iterable() is better-suited for this operation, as it assumes a single iterable of iterables to begin with. Your code then becomes simply:
uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))
It splits the sequence into separate arguments for the function call.
>>> def foo(a, b=None, c=None):
... print a, b, c
...
>>> foo([1, 2, 3])
[1, 2, 3] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
... print a
...
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)
Just an alternative way of explaining the concept/using it.
import random
def arbitrary():
return [x for x in range(1, random.randint(3,10))]
a, b, *rest = arbitrary()
# a = 1
# b = 2
# rest = [3,4,5]

What does * mean in python function? [duplicate]

This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 2 years ago.
Here is one easy math function in Jupyter using Python 3
def sum(*formulation):
ans = 0
for i in formulation:
ans += i
return ans
If I want to try this function, I write down like this:
sum(1,2,3,4)
The output will be
10
My question is what is * mean in sum(*formulation)?
Because if I don't use *, I get an error.
The "*" and then "**" notation are called "packing" and "unpacking". The main idea is that if you unpack objects, the they are removed from their list/dict and if you pack objects, then they are placed into a list/dict. For example,
x = [*[1,2,3],4]
print(x)
Here I have "unpacked" the [1,2,3] into the list for "x". Hence, x is now [1,2,3,4]. Here is another example,
d1 = {'x':7}
d2 = {'y':10}
d3 = {**d1,**d2}
Here I have dictionary "unpacked" the first two dictionaries into the third one. Here is another example:
def func(*args):
print(args)
func(1,2,3,4,5)
Here the 1,2,3,4,5 are not in a list, hence they will be "packed" into a list called args in the func.
That is called a starred expression. In the argument list of a function, this means that all other supplied positional arguments (that are not caught by preceding positional arguments) will be "packed" into the starred variable as a list.
So
def function(*arguments):
print(arguments)
function(1, 2, 3)
will return
[1, 2, 3]
Note that it has different behaviour in other contexts in which it is usually used to "unpack" lists or other iterables. The Searchwords for that would be "starred", "packing" and "unpacking".
A good mnemonic for unpacking is that they remove the list brackets
a, b, c = *[1, 2, 3] #equivalent to
a, b, c = 1, 2, 3
And for packing like a regex wildcard
def function(*arguments):
pass
def function(zero, or_, more, arguments):
pass
head, *everything_in_between, tail = [1, 2, 3, 4, 5, 6]
It means that the function takes zero or more arguments and the passed arguments would be collected in a list called formulation.
For example, when you call sum(1, 2, 3, 4), formation would end up being [1, 2, 3, 4].
Another similar but different usage of * that you might come across is when calling the function. Say you have a function defined as def add(a, b), and you have a list l = [1, 2], when you call add(*l) it means to unpack l and is equivalent to add(l[0], l[1]).

transform array of arrays into arguments for a function in Python [duplicate]

This question already has answers here:
Pass a list to a function to act as multiple arguments [duplicate]
(3 answers)
Closed 2 years ago.
I want to use a function that takes *args:arrays as arguments (so f(a,b,c,...,z) where a,b,...z are arrays.
I have my variables stored as array_vars = [a,b,c,...,z].
How do I transform array_vars so that the function f understands ?
You just need to * operator to unpack the items from a list.
f(*array_vars)
Example
>>> def f(*args):
... for x in args:
... print(x)
...
>>> f(1, 2, 3)
1
2
3
>>> f(*[1, 2, 3])
1
2
3
With * you can unpack arguments from a list or tuple and ** unpacks arguments from a dict.
>>> range(3, 6) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5]

python list comprehension and extend() [duplicate]

This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 5 months ago.
Working my way into Python (2.7.1)
But failing to make sense (for hours) of this:
>>> a = [1, 2]
>>> b = [3, 4]
>>>
>>> a.extend([b[0]])
>>> a
[1, 2, 3]
>>>
>>> a.extend([b[1]])
>>> a
[1, 2, 3, 4]
>>>
>>> m = [a.extend([b[i]]) for i in range(len(b))] # list of lists
>>> m
[None, None]
The first two extends work as expected, but when compacting the same in a list comprehension it fails.
What am i doing wrong?
extend modifies the list in-place.
>>> [a + b[0:i] for i in range(len(b)+1)]
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]
list.extend() extends a list in place. Python standard library methods that alter objects in-place always return None (the default); your list comprehension executed a.extend() twice and thus the resulting list consists of two None return values.
Your a.extend() calls otherwise worked just fine; if you were to print a it would show:
[1, 2, 3, 4, 3, 4]
You don't see the None return value in the Python interpreter, because the interpreter never echoes None results. You could test for that explicitly:
>>> a = []
>>> a.extend(['foo', 'bar']) is None
True
>>> a
['foo', 'bar']
the return value of extend is None.
extend function extends the list with the value you've provided in-place and returns None. That's why you have two None values in your list. I propose you rewrite your comprehension like so:
a = [1, 2]
b = [3, 4]
m = [a + [v] for v in b] # m is [[1,2,3],[1,2,4]]
For python lists, methods that change the list work in place and return None. This applies to extendas well as to append, remove, insert, ...
In reply to an older question, I sketched an subclass of list that would behave as you expected list to work.
Why does [].append() not work in python?
This is intended as educational. For pros and cons.. look at the comments to my answer.
I like this for the ability of chaining methods and working in a fluent style, e.g. then something like
li = FluentList()
li.extend([1,4,6]).remove(4).append(7).insert(1,10).reverse().sort(key=lambda x:x%2)
would be possible.
a.extend() returns None.
You probably want one of these:
>>> m = a + b
>>> m
[1, 2, 3, 4]
>>> a.extend(b)
>>> a
[1, 2, 3, 4]
Aside from that, if you want to iterate over all elements of a list, you just can do it like that:
m = [somefunction(element) for element in somelist]
or
for element in somelist:
do_some_thing(element)
In most cases there is no need to go over the indices.
And if you want to add just one element to a list, you should use somelist.append(element) instead of `somelist.extend([element])

python array as list of parameters

I have an array that matches the parameters of a function:
TmpfieldNames = []
TmpfieldNames.append(Trademark.name)
TmpfieldNames.append(Trademark.id)
return func(Trademark.name, Trademark.id)
func(Trademark.name.Trademark.id) works, but func(TmpfieldNames) doesn't. How can I call the function without explicitly indexing into the array like func(TmpfieldNames[0], TmpfieldNames[1])?
With * you can unpack arguments from a list or tuple and ** unpacks arguments from a dict.
>>> range(3, 6) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5]
Example from the documentation.
I think what you are looking for is this:
def f(a, b):
print a, b
arr = [1, 2]
f(*arr)
What you are looking for is:
func(*TmpfieldNames)
But this isn't the typical use case for such a feature; I'm assuming you've created it for demonstration.

Categories