ax.plot() returns a tuple with one element. By adding the comma to the assignment target list, you ask Python to unpack the return value and assign it to each variable named to the left in turn.
Most often, you see this being applied for functions with more than one return value:
base, ext = os.path.splitext(filename)
The left-hand side can, however, contain any number of elements, and provided it is a tuple or list of variables the unpacking will take place.
In Python, it's the comma that makes something a tuple:
>>> 1
1
>>> 1,
(1,)
The parenthesis are optional in most locations. You could rewrite the original code with parenthesis without changing the meaning:
(line,) = ax.plot(x, np.sin(x))
Or you could use list syntax too:
[line] = ax.plot(x, np.sin(x))
Or, you could recast it to lines that do not use tuple unpacking:
line = ax.plot(x, np.sin(x))[0]
or
lines = ax.plot(x, np.sin(x))
def animate(i):
lines[0].set_ydata(np.sin(x+i/10.0)) # update the data
return lines
#Init only required for blitting to give a clean slate.
def init():
lines[0].set_ydata(np.ma.array(x, mask=True))
return lines
For full details on how assignments work with respect to unpacking, see the Assignment Statements documentation.
Answer from Martijn Pieters on Stack Overflowax.plot() returns a tuple with one element. By adding the comma to the assignment target list, you ask Python to unpack the return value and assign it to each variable named to the left in turn.
Most often, you see this being applied for functions with more than one return value:
base, ext = os.path.splitext(filename)
The left-hand side can, however, contain any number of elements, and provided it is a tuple or list of variables the unpacking will take place.
In Python, it's the comma that makes something a tuple:
>>> 1
1
>>> 1,
(1,)
The parenthesis are optional in most locations. You could rewrite the original code with parenthesis without changing the meaning:
(line,) = ax.plot(x, np.sin(x))
Or you could use list syntax too:
[line] = ax.plot(x, np.sin(x))
Or, you could recast it to lines that do not use tuple unpacking:
line = ax.plot(x, np.sin(x))[0]
or
lines = ax.plot(x, np.sin(x))
def animate(i):
lines[0].set_ydata(np.sin(x+i/10.0)) # update the data
return lines
#Init only required for blitting to give a clean slate.
def init():
lines[0].set_ydata(np.ma.array(x, mask=True))
return lines
For full details on how assignments work with respect to unpacking, see the Assignment Statements documentation.
If you have
x, = y
you unpack a list or tuple of length one. e.g.
x, = [1]
will result in x == 1, while
x = [1]
gives x == [1]
Noob here
if I had this as my code...
print('The',highway_number,'is auxiliary, serving the',highway_two_digits,", going", end = ' ')
how would I add a comma after the varible highway_two_digits so that it said
The 405 is auxiliary, serving the 5, going north/south.
I can put a comma in, put i'm not sure how to make it so that it is directly after the variable rather than a space in between the variable and the comma.
sorry if this is confusing because it is for me too lol
Videos
Sorry for the title gore.
This program tells the user what their MPG was at the end of their trip.
Output that I need help revising:
print('Your car make and model is a', make_and_model_of_vehicle, 'you travelled', miles_travelled, 'miles and used', gallons_used, 'gallons of gas so your gas mileage is', gas_mileage, 'MPG.')The issue I'm having is wanting to add a comma after "make_and_model_of_vehicle" so it's grammatically correct, however I have been unable to do so.
It is the commas, not the parentheses, which are significant. The Python tutorial says:
A tuple consists of a number of values separated by commas
Parentheses are used for disambiguation in other places where commas are used, for example, enabling you to nest or enter a tuple as part of an argument list.
See the Python Tutorial section on Tuples and Sequences
Because this is the only way to write a tuple literal with one element. For list literals, the necessary brackets make the syntax unique, but because parantheses can also denote grouping, enclosing an expression in parentheses doesn't turn it into a tuple: you need a different syntactic element, in this case the comma.
What you describe is tuple assignment:
a, b = 0, 1
is equivalent to a = 0 and b = 1.
It can however have interesting effects if you for instance want to swap values. Like:
a,b = b,a
will first construct a tuple (b,a) and then untuple it and assign it to a and b. This is thus not equivalent to:
#not equal to
a = b
b = a
but to (using a temporary):
t = a
a = b
b = t
In general if you have a comma-separated list of variables left of the assignment operator and an expression that generates a tuple, the tuple is unpacked and stored in the values. So:
t = (1,'a',None)
a,b,c = t
will assign 1 to a, 'a' to b and None to c. Note that this is not syntactical sugar: the compiler does not look whether the number of variables on the left is the same as the length of the tuple on the right, so you can return tuples from functions, etc. and unpack them in separate variables.
For the purposes of reading, all it's doing is setting a and b, so that a = 0 and b = 1. Similarly, in line 7, it's setting a to b and b to the sum of a and b.
More specifically, it's setting tuples. Tuples are invariant, in that once they're created, their values can't change. Tuples are pervasive in python - you see them almost everywhere.
Typically, you would expect a tuple to be in parenthesis, e.g. (a, b) = (0, 1) would read more cleanly, but they are such a large feature of python that the parenthesis are optional (unless you're constructing a tuple as an argument to a function, and then you need the extra parenthesis to differentiate between a single tuple and multiple arguments. I.e. you would have to say foo((a, b)) to pass a tuple to foo, as foo(a, b) would pass two arguments to it.)
Tuples can be any length. You can write a, b, c, d, e = 0, 1, 2, 3, 4, or you can have a function return a tuple, e.g.: ret1, ret2, ret3 = foobar(1)
d2, = values[s] is just like a,b=f(), except for unpacking 1 element tuples.
>>> T=(1,)
>>> a=T
>>> a
(1,)
>>> b,=T
>>> b
1
>>>
a is tuple, b is an integer.
_ is like any other variable name but usually it means "I don't care about this variable".
The second question: it is "value unpacking". When a function returns a tuple, you can unpack its elements.
>>> x=("v1", "v2")
>>> a,b = x
>>> print a,b
v1 v2
The problem is pretty straightforward, and your solution is as well. I have only a couple of small comments:
- The
popmethod in Python removes and returns the last item in a list, which can replace two lines. - You don't have to
new_string = ''when you setnew_stringon the next line. As a result, things can be shortened a bit. - Personally, since
str1is only used once, I would personally just do it inline and not save it to a variable. The only time I save something to a variable, if it is only used once, is to shorten an otherwise-long line. - Concatenating two hard-coded strings should be put in one operation (i.e.
' and' + ' '=>' and ' - Guards! They're the best way to check input before executing.
My recommended version:
def items(some_list):
if not some_list:
return ''
string_end = some_list.pop()
if not some_list:
return string_end
and_display = ' and ' if len(some_list) == 1 else ', and '
new_string = ', '.join(some_list) + and_display + string_end
return new_string
print(items(['apples', 'kittens', 'tofu', 'puppies']))
This works fine as long as you are working with a list of strings. It will crash if you pass in an int or something that can't auto-convert to a string. That may or may not be a problem, depending on your perspective. Trying to make your code auto-convert things to strings, if they aren't strings, can be a very error-prone process. As a result, I think it is perfectly fine to write this the easy way, and let it be the developer's problem if it crashes due to non-string arguments.
Docstrings are usually helpful for this kind of thing.
Note on pass-by-reference
Hat tip to TheEspinosa: Python uses a pass-by-reference style for its arguments. As a result, modifying arguments (which is especially easy for lists, as is the case here) can result in unintentional side-effects. The use of pop (or del in your original code) results in the last entry being removed from the list, not just inside the function, but also in the variable passed in to the function. For your example usage, which calls this function with a constant value, this behavior doesn't matter. But it may as part of a larger application. There are three ways to handle this:
- Adjust your algorithm so you don't make any changes to any arguments being passed in (@Richard Nemann's answer works that way)
- Copy the list before using it inside your function. A simple shorthand to copy a list is:
new_copy = old_copy[:]. There is also a copy module. - Ignore it and let it be the caller's problem.
I use all three solutions depending on the circumstances or my mood. A copy operation obviously involves some overhead, but unless you know that performance is a problem, I would still do a copy if the algorithm that avoids the need for the copy is harder to understand.
To be clear about the problem the current code can potentially introduce, try running my implementation (or yours) like this:
vals = ['apples', 'bananas', 'grapes']
items(vals)
print(len(vals))
If you run this code the last line will print 2, because in your calling scope the variable has been modified-by-reference: grapes is no longer in the list.
I said at the beginning that this was a straightforward problem. At this point in time though I think it's fair to say that the devil is in the details :)
Your problem can be reduced to:
def list_english(items):
"""Returns a comma-separated string of the list's items,
separating the last item with an 'and'.
"""
if not items:
return ''
if len(items) == 1:
return items[0]
return '{}, and {}'.format(', '.join(items[:-1]), items[-1])
Note that variable and function names in python are to be named with underscore-separated lower-case according to PEP 8.
Also consider using docstrings to state, what a function's purpose is.
if __name__ == '__main__':
print(list_english(['apples', 'kittens', 'tofu', 'puppies']))
Also enclose your script code in an if __name__ == '__main__': block to prevent it from being run if the module is solely imported.
Finally, consider your variable naming. Python has dynamic typing, so expressive names are especially important.