Related
I have a function that takes two inputs, both tuples, and checks to ensure they are the same size before continuing. I am having issues in trying to calculate the length of each tuple.
Examples:
tupA = ([1,2,3,4],[11,22,33,44])
tupB = ([1,2],[3,4],[5,6])
tupC = ([1,2,3,4,5,6,7,8,9])
When I take the length of each object it returns:
len(tupA) = 2
len(tupB) = 3
len(tupC) = 9
Is there an easy way to have the len(tupC) return 1? I found a workaround by adding a comma:
tupD = ([1,2,3,4,5,6],)
len(tupD) = 1
But I don't want to force the user to have to add the comma. Is there a better way to do this?
For such data
tupA = ([1,2,3,4],[11,22,33,44])
tupB = ([1,2],[3,4],[5,6])
tupC = ([1,2,3,4,5,6,7,8,9])
last one is not tuple, as you might check
print(type(tupC)) #prints <class 'list'>
You might check if variable is of given type using isinstance function, you could therefore create own function
def mylen(x):
if isinstance(x,list):
return 1
else:
return len(x)
Which will give 1 for your tupC, 3 for your tupB and 2 for your tupA.
You would have to have the comma to make the len work as you expect, as mentioned in the docs
A tuple with one item is constructed by following a value with a comma.
The only benefit of a tuple would be to make it immutable,
but if you use lists, there is no problem.
>>> listA = [[1,2,3,4],[11,22,33,44]]
>>> listB = [[1,2],[3,4],[5,6]]
>>> listC = [[1,2,3,4,5,6,7,8,9]]
>>> len(listA)
2
>>> len(listB)
3
>>> len(listC)
1
As discussed in comments, tupC is not a tuple, it's a list with 9 elements. It's a tuple only when there is a trailing comma.
As a workaround, we can check if it's a list and return results accordingly:
def length_(tupl):
return 1 if isinstance(tupl, list) else len(tupl)
Usage:
>>> tupA = ([1,2,3,4],[11,22,33,44])
>>> tupB = ([1,2],[3,4],[5,6])
>>> tupC = ([1,2,3,4,5,6,7,8,9])
>>> length_(tupA)
2
>>> length_(tupB)
3
>>> length_(tupC)
1
Notice that tupC is actually a list, not a tuple:
>>> tupA = ([1,2,3,4],[11,22,33,44])
>>> tupB = ([1,2],[3,4],[5,6])
>>> tupC = ([1,2,3,4,5,6,7,8,9])
>>> type(tupA), type(tupB), type(tupC)
(<class 'tuple'>, <class 'tuple'>, <class 'list'>)
If you still insist on keeping things as tuples of lists instead of lists of lists, and don't want to add the comma, you could define your own function to handle this:
>>> def newlength(x):
... if type(x) == list:
... return 1
... return len(x)
...
>>> print(newlength(tupA))
2
>>> print(newlength(tupB))
3
>>> print(newlength(tupC))
1
EDIT: Kudos to Daweo for beating me to an almost identical answer by a couple of minutes!
There is a formatting question, that I would like some additional insight/understanding on. I have the following code:
In[1]:
mylist = [[99]]
for [x] in mylist:
print(x)
Out[1]:
99
My main question is regarding the []s around the x in the second line. So I have never used []s before when describing the 'x' variable of a loop. Since my output is 99 and not [99], it looks like the []s are going to ask the loop to extract the number from its additional set of brackets.
Question Updated Based on Responses:
If I change the code to remove the brackets:
In[1]:
mylist = [[99]]
for x in mylist:
print(x)
Out[1]:
[99]
I get [99] instead of 99. However, if I do the following:
In[1]:
mylist = [[99,100]]
for x,y in mylist:
print(x)
print(y)
Out[1]:
99
100
This example above doesn't require an additional set of []s around x,y and produces a bracket-less answer in the output, unlike the previous two examples, which requires a [] to produce a bracket-less answer.
I realize this is an odd and fairly silly question since I would never construct a single element list like this. I simply saw this being casually used in an answer elsewhere online (with no explanation on it unfortunately). Being a newcomer, I'm just curious to broaden my understanding of the language.
Thanks in advance.
When you do this:
>>> myList = [[99]]
>>> for x in myList:
print x
Python interprets that as "print each element in this iterable".
When you do this:
>>> myList = [[99,100], [99,101], [99, 102]]
>>> for x in myList:
print x
Python still interprets that as "print each element in this iterable" so that you get this:
[99, 100]
[99, 101]
[99, 102]
But, if you do this:
>>> myList = [[99,100], [99,101], [99, 102]]
>>> for x, y in myList:
print x, y
Python will "unpack" the values for you from each element in the iterable and assign them to x and y. If you want to do that above for only the case of myList = [[99]], Python requires the for [x] in myList syntax so that it unpacks the single value from the list.
The ability to "unpack" an iterable is very powerful in Python. You can assign variables on the fly by unpacking an iterable. In your case, you can imagine having to assign lat lon as variables maybe or something else. You can also unpack values into the args of a function.
In Python 3 you can also do something like this:
x = [1,2,3,4]
first, *rest = x
print (first) # 1
print (rest) # [2,3,4]
For the second example, with lists of length 2, to unpack both values you can do
In[1]:
myList = [[99,100]]
for x, y in myList:
print(x)
print(y)
Out[1]:
99
100
As per Python documentation, the square brackets are essentially ignored in assignments and loop constructs.
So as a complement to user2774697's answer, for x, y in L is equivalent to for [x, y] in L which is equivalent to for ([x, y]) in L and is also equivalent to for (x, y) in L.
The thing that the square brackets do different than a bare round parenthesis is that it enforces an unpacking behavior, it requires the elements in L to be iterable.
Below code works. However I cannot re-create it/not understand it. Could someone pls help to write all lines to complete the code.
value = #something
var1, var2 = unpack("b8s",value)
That means, here one value is being put into two variables. Can someone give an example, how its possible?
Many thanks in advance.
You're over complicating it by having a loop at all.
var1, var2 = tuple
This is just a syntax thing you can do in python. Note that you must unpack the entire tuple; the number of variables on the left-hand side must be equal to the number of values in the tuple.
Example
myTuple = ("hi","i","am","tuple")
first,second,third,fourth = myTuple
print first
>>hi
print second
>>i
print third
>>am
print fourth
>>tuple
Not allowed
myTuple = ("hi","i","am","tuple")
first,second = myTuple
>>Exception
The unpack method is coming from the struct module, which is lets you treat a Python string like packed binary data. The unpack('b8s', value) call is telling unpack to treat value like a binary string containing one unsigned char (using 'b'), which will be unpacked as the integer value of the char, followed by a char[8] (using '8s'), meaning a char string of length 8. That gets unpacked as a Python string. So a full example would look like this:
>>> from struct import unpack
>>> s = "abcdefgty"
>>> int_char, my_str = unpack("b8s", s)
>>> print int_char
97 # 97 is the ascii code of 'a'
>>> print my_str
bcdefgty
If you have a tuple as
t = (1, 2, "a")
you can unpack it like this:
a, b, c = t
print "a=", a
which prints
a= 1
What is happening is: unpack process the contents of elem and returning a tuple with 2 items. Each item is assigned to a different variable.
it's the same:
unpacked_value = unpack("b8s",elem)
var1 = unpacked_value[0]
var2 = unpacked_value[1]
Using diffentd values and variables:
my_tuple = (1, 2)
var1, var2 = my_tuple
print var1 #outputs 1
print var2 #outputs 2
This question already has answers here:
How are tuples unpacked in for loops?
(8 answers)
Closed 9 years ago.
I'm new to python and trying to work my way through http://yuji.wordpress.com/2011/06/22/python-imaplib-imap-example-with-gmail/ which has the following line:
result, data = mail.uid('search', None, "ALL") # search and return uids instead
Could someone explain this line?
Thank you.
It means that the function you have called returns an iterable, and the index 0 of the iterable is assigned to x and the index 1 is assigned to y. This is called tuple unpacking.
Eg)
>>> def func(a,b):
... return b,a
...
>>> a = 5
>>> b = 7
>>> a,b = func(a,b)
>>> a
7
>>> b
5
>>> x = func(a,b)
>>> x
(5, 7)
Edit to show that returning multiple values, they are packed as tuple by default and then unpacked at the other end. Since there is only one variable x here, the tuple is assigned to x.
Simple function for swapping two variables(Just for an example) that answers your question
At least, as of python 2.7.x, the function will unpack a tuple of 2 arguments returned from a function. If it returns anything other than 2 arguments in the tuple, I believe it will throw an error if you try to unpack more than this. If it returns 3 arguments and you unpack 2, for example, you will get an exception.
For example:
def func(a):
return (a,a+1,a*2)
a,b,c = func(7)
print a,b
==> 7 8 # NOTE Values
a = func(3)
print a
==> (3, 4, 6) # NOTE: TUPLE
a,b = func(9)
print a,b
==> Exception - ValueError: too many values to unpack
This may be different in 3.0+.
The other answer, that "the function you have called returns an iterable" is a good one. That is what is happening in your specific example. This is what is called "unpacking" in python. The following are examples of unpacking and assignment related to your question:
>>> a,b = 1,2
>>> a
1
>>> b
2
>>> a,b,c = ['do', 're', 'mi']
>>> a
'do'
>>> b
're'
>>> c
'mi'
>>>
This is one of the pretty features of Python syntax. If I am not mistaken, it is also optimized - i.e. the fastest way to achieve the result.
Apologies if this doesn't make any sense, I'm very new to Python!
From testing in an interpreter, I can see that list() and [] both produce an empty list:
>>> list()
[]
>>> []
[]
From what I've learned so far, the only way to create an object is to call its constructor (__init__), but I don't see this happening when I just type []. So by executing [], is Python then mapping that to a call to list()?
Those two constructs are handled quite differently:
>>> import dis
>>> def f(): return []
...
>>> dis.dis(f)
1 0 BUILD_LIST 0
3 RETURN_VALUE
>>> def f(): return list()
...
>>> dis.dis(f)
1 0 LOAD_GLOBAL 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
>>>
The [] form constructs a list using the opcode BUILD_LIST, whereas the list() form calls the list object's constructor.
No, Python does not call list(), or you could affect what type [] creates by assigning to list, which you cant:
>>> import __builtin__
>>> __builtin__.list = set
>>> list()
set([])
>>> []
[]
[] is syntax for creating a list. It's a builtin type and it has special syntax, just like dicts and strings and ints and floats and lots of other types.
Creating instances of types can also be done by calling the type, like list() -- which will in turn call the type's constructor and initializer for you. Calling the initializer (__init__) directly does not create a new instance of the type. Calling the constructor (__new__) does, but you should not be calling it directly.
I started learning python yesterday....
I guess you would have to say its internally mapped
>>> a = []
>>> type(a)
<type 'list'>
>>> a = list()
>>> type(a)
<type 'list'>
What are the key differences between using list() and []?
The most obvious and visible key difference between list() and [] is the syntax. Putting the syntax aside for a minute here, someone whose new or intermediately exposed to python might argue that they’re both lists or derive from the same class; that is true. Which furthermore increases the importance of understanding the key differences of both, most of which are outlined below.
list() is a function and [] is literal syntax.
Let’s take a look at what happens when we call list() and [] respectively through the disassembler.
>>> import dis
>>> print(dis.dis(lambda: list()))
1 0 LOAD_GLOBAL 0 (list)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 RETURN_VALUE
None
>>> print(dis.dis(lambda: []))
1 0 BUILD_LIST 0
3 RETURN_VALUE
None
The output from the disassembler above shows that the literal syntax version doesn’t require a global lookup, denoted by the op code LOAD_GLOBAL or a function call, denoted by the op code CALL_FUNCTION.
As a result, literal syntax is faster than it’s counterpart. – Let’s take a second and look at the timings below.
import timeit
>>> timeit.timeit('[]', number=10**4)
0.0014592369552701712
>>> timeit.timeit('list()', number=10**4)
0.0033833282068371773
On another note it’s equally important and worth pointing out that literal syntax, [] does not unpack values. An example of unpacking is shown below.
>>> list('abc') # unpacks value
['a', 'b', 'c']
>>> ['abc'] # value remains packed
['abc']
What’s a literal in python?
Literals are notations or a way of writing constant or raw variable values which python recognises as built-in types.
Sourced from my post on PythonRight - what's the difference between list and [].
In addition to the other answers, from the Language Reference:
A list display is a possibly empty series of expressions enclosed in square brackets:
list_display ::= "[" [expression_list | list_comprehension] "]"
...
A list display yields a new list object.
It does not explicitly mention how "yielding a new list object" is implemented. It could well be a call to the list() constructor, like you mentioned. Or maybe lists, being so elementary, get special treatment, and list() is actually mapped to something different entirely.
Either way, [] is certainly not mapped to a call to the constructor of the type named __builtins__.list, because redefining that type still causes [] to return an actual list, as other answerers have shown.
Python, like most programming langauges, has something called literals, meaning that special syntax can be used to write out some of the most important types of values. Very little of this is necessary, but it makes it easier to use Python that we can write literals.
>>> 0
0
>>> int()
0
>>> 5
5
>>> int('5') # I'm using a string literal here though!
5
>>> 0.0
0.0
>>> float()
0.0
>>> ""
''
>>> str()
''
>>> u""
u''
>>> unicode()
u''
>>> ()
()
>>> tuple()
()
>>> {}
{}
>>> dict()
{}
When we make our own types (classes), we create instances of them using their constructors, like list for lists. When we use literals, it's sort of like syntactic sugar for calling list, but in reality it calls that same basic things behind the scene.
Since :
class list(object):
"""
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
"""
If the element in your lists is an iterable (i.e. a str), the list() and [] don't work the same way.
So
>>> a = ['ab']
>>> b = list('ab')
>>> a[0]
'ab'
>>> b[0]
'a'