Distinction between python str and tuple objects [duplicate] - python

This question already has answers here:
Why does adding a trailing comma after an expression create a tuple?
(6 answers)
Closed 6 years ago.
How python initializes a tuple object ?
For example, when I create an object like
>>> object = ('Shark')
It shows type of object as str
>>> type(object)
<type 'str'>
While, if I create an object like
>>> object = ('Shark',)
It displays its type as a tuple
>>> type(object)
<type 'tuple'>
Why so ?? How exactly python creates/initializes a tuple, str objects ?

From docs:
A special problem is the construction of tuples containing 0 or 1
items: the syntax has some extra quirks to accommodate these. Empty
tuples are constructed by an empty pair of parentheses; a tuple with
one item is constructed by following a value with a comma (it is not
sufficient to enclose a single value in parentheses).
So, without a trailing , these two statements are equivalent:
>>> x = 1
>>> x
1
>>> x = (1)
>>> x
1
But these are all tuples:
>>> x = 1, #or (1,)
>>> x
(1,)
>>> x = 1, 2, 3 #or (1, 2, 3)
>>> x
(1, 2, 3)

An expression enclosed in parens is just that expression (it's like the parens in a math expression, like (2+2)*4).
But, if you add a trailing comma, or if there's more than one element inside the parens separated by commas, it will become a tuple. Also, you will get an empty tuple if you write ().

Anything enclosed inside double-quotes or single-quotes will be treated as a string in Python. There's no distinction between the two-- like in PHP, that variables inside the double-quoted strings will actually be evaluated and single-quotes will display as it is.
Anything enclosed inside an opening parenthesis and closing parenthesis will be treated as tuples. However, if only one object has been placed in the tuple, it'll be treated as the object's type. For instance:
>>> a = (9)
>>> type(a)
<class 'int'>
>>>
>>> a = ([9])
>>> type(a)
<class 'list'>
>>>
>>> a = ('hello!')
>>> type(a)
<class 'str'>
>>>
>>> a = {'a':1, 'b':1}
>>> type(a)
<class 'dict'>
>>>
Note that the length of the object doesn't matter (the object placed inside of the tuple, not the tuple itself).
Now, if you were to place a comma after the object inside of the tuple, Python will presume that there's another object coming and it'll treat it as if it were a tuple and not give you an error. Also, note that the default object used by Python to store a number of things is also a tuple-- meaning that even if you don't enclose an expression in parenthesis, it'll do it by default for you:
>>> a = 9, 8, 7
>>> a
(9, 8, 7)
>>> type(a)
<class 'tuple'>
>>>
>>> a = 'Hello', 'Python', 'Typle'
>>> a
('Hello', 'Python', 'Typle')
>>> type(a)
<class 'tuple'>
>>>

Related

Inconsistency in printing tuples in python

I have just started to learn python and following the docs on tuples, I came across this snippet,
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)
Following this I ran following snippet,
>>> foo=1,2,3,
>>> len(foo)
3
>>> foo
(1, 2, 3)
Why does singleton prints with an trailing comma , where as foo seems to trim it ?
Beacause ("Hello") is not a tuple, it is same as "Hello".
>>> ("Hello")
'Hello'
in order to distinguish tuple with single element from a simple expression in () a , is necessary. Whereas (1,2,3) is clearly a collection of items, and as they are enclosed by () it can easily be inferred as a tuple, hence no need for a trailing ,.
because you define variable"singleton" as ("hello",), you don't need comma to end it, and for "foo", you define it, so it shows as what you defined

Compare non identical objects with same value

I have 2 lists,both in different formats but same content.
For example, doing a simple print command for the 1st elements of the list does the following:
prefix_txt[0]=SEF00
prefix_confluence[0]=[u'SEF00']
I get the 'u' here is due to the encoding..
The prefix_confluence is being parsed by a HTML parser this way:
soup=BeautifulSoup(sample,'html.parser')
for row in soup.find_all('tr')[2:171]:
prefix_confluence.append(row.get_text(strip=True, separator='|').split('|')[0:1])
Now, how do I compare and show that these 2 list elements are in fact equal in content?
I have tried this:
new=str(prefix_confluence[0]).strip('[u'']')
if(prefix_txt[0]==new):
print "They are same."
But they dont display the print message due to obvious reasons.
How can I make them equal? I also tried join, concatenation but was not able to make it work.
If prefix_txt[0] is a string 'SEF00', and prefix_confluence[0] is a list containing a unicode version of that same string [u'SEF00'], then you should be able to do the following:
new = prefix_confluence[0][0]
if(prefix_txt[0] == new):
print "They are same."
When you do new = str(prefix_confluence[0]).strip('[u'']') you will get the string "'SEF00'", which as you can see is slightly different from the string 'SEF00'. Instead, you can get the string out of the list by indexing the list: prefix_confluence[0][0], which will give you u'SEF00'. Although this looks different from 'SEF00', in Python 2.x they are seen as equal; i.e., 'SEF00' == u'SEF00' is True, although their types are different and they do not point to the same object:
>>> a = 'foo'
>>> b = u'foo'
>>> a == b
True
>>> a is b
False
>>> type(a)
<type 'str'>
>>> type(b)
<type 'unicode'>
And for completeness, the same solution will work in Python 3.x, although what is happening is slightly different. In Python 3, all strings are unicode by default, so not only are 'SEF00' and u'SEF00' equal in Python 3, they should generally point to the same object as far as I know:
>>> a = 'foo'
>>> b = u'foo'
>>> a == b
True
>>> a is b
True
>>> type(a)
<class 'str'>
>>> type(b)
<class 'str'>

literal_eval of tuple with a single element

I am using ast.literal_eval(str) to evaluate a string containing a tuple such as ('a', 'b', 'c'). However, if for some reason this tuple only contains a single element, the expression ignores the parenthesis and returns only the element:
>>> string = "('a')"
>>> x = ast.literal_eval(string)
>>> x
'a'
Is there a non-hackish way to solve this? This problem is exacerbated by the fact that sometimes, I might have a tuple of tuples, like (('a','b')) and as such cannot just check for type. Thanks!
That is because ('a') is not a tuple but a string treated as a. Tuple with only one object is defined as ('a',) (note the ,)
>>> type('a')
<type 'str'> <-- String
>>> type(('a'))
<type 'str'> <-- String
>>> type(('a',))
<type 'tuple'> <-- Tuple

converting singletone tuple to list

a=(3)
b=list(a)
typeError: 'int' object is not iterable
but
a=[3]
b=tuple(a)
c=list(b)
runs without error.
please explain this.
That's because (3) is just 3. tuples are defined by the comma, not the parentheses. If you want a tuple with one element, add a comma: (3,).
(3) is the number 3 in parentheses and (3,) is a tuple:
>>> a = (3)
>>> type(a)
<type 'int'>
>>> a = (3,)
>>> type(a)
<type 'tuple'>
There are no ambiguity with [3] so it's a list:
>>> a = [3]
>>> type(a)
<type 'list'>
The list constructor accepts a tuple or a list but not a int.
Define tuple by using comma ,
type((3,)) its of type 'tuple'
type(3) its of type 'int'

How to find if the data is a str or int in List

If I have a list as below:
samplist= [3,4,5,'abc']
How can I find out whether which index is a str or Int.I want to concatenate a string s='def' with the string 'abc' which is available in the list.
Assume that I am not aware I don't know anything about the string, neither the name nor its index in list. All i know is there is a string in the list samplist and I want to loop through and find it out so that it can be concatenated with string s='def'/.
for i in xrange(len(samplist)):
if isinstace(samplist[i], str):
samplist[i] += 'def'
type() command also works:
>>> list = [1, 2, 'abc']
>>> type(list)
<class 'list'>
>>> type(list[1])
<class 'int'>
>>> type(list[2])
<class 'str'>
>>> type(list[2]) is str
True
>>> type(list[1]) is str
False

Categories

Resources