Python convert list of one element into string with bracket - python

How to convert python list containing one element to string with bracket?
For more than one element, its easy for me to just just use tuple(list['a','b']) which returns as tuple ('a','b') but if element is one, it returns as ('a',) but rather I want to return ('a')
sample:
mylist = ["a", " b"]
print tuple([s.strip() for s in mylist])
>> ('a', 'b')
mylist = ["a"]
print tuple([s.strip() for s in mylist])
>> ('a', ) #rather I want to return ('a')

Avoid relying on default __repr__() method, to format strings, they might change.
Be explicit about your intent instead
print "('" + "', '".join(mylist) + "')"

>>> ('a') == 'a'
True
If you're not going to use a single element tuple, then the parenthesis are only grouping parenthesis (not a container), and they won't stick like you want them to, except you include them as part of the string with a or define a custom print function.
With the custom print function, you get to keep the conversion from list to tuple (i.e. t = tuple(mylist)) as is and also use the single element tuple as is:
def tuple_print(t):
print(str(t).replace(',', '') if len(t) == 1 else t)
Trials:
>>> def tuple_print(t):
... print(str(t).replace(',', '') if len(t) == 1 else t)
...
>>> mylist = ["a"]
>>> t = tuple(mylist)
>>> t
('a',)
>>> tuple_print(t)
('a')
>>> t = ('a', 'b')
>>> tuple_print(t)
('a', 'b')

Related

Python Function returning string with quotes

I have a function and returning three values, The return value for my function is
(1, 3, "<class 'int'>")
while I want to return
(1, 3, <class 'int'>)
How do I remove the quotes from my return value.str(type(element)) is the value which is returning the 3rd value
def is_list_permutation(L1, L2):
L1set = set(L1)
L2set = set(L2)
count = 0
element = ''
if L1 == [] and L2 == []:
return(None,None,None)
elif len(L1) == len(L2) and L1set == L2set:
for a in L1:
if L1.count(a) == L2.count(a):
if L1.count(a) > count:
count = L1.count(a)
element = a
return(element,count,str(type(element)))
else:
return False
break
else:
return False
so if i give
L1 = [1, 'b', 1, 'c', 'c', 1]
L2 = ['c', 1, 'b', 1, 1, 'c']
then the result is (1, 3, "<class 'int'>") while I want (1, 3, <class 'int'>)
Your function is returning a tuple with three elements: element, count and the string representation of the type of element. At no point, this has any string representation which you’re seeing there. You just get back a tuple.
Now, when you print that tuple, then the print function will actually try to convert it into a string. For a tuple, this string representation is defined to be a set of parentheses (), and the repr() string representation of each tuple element inside.
For numbers, this will look fine since repr(5) happens to be the string '5'. But for strings, the repr will add quotes to make sure that the return string would be valid Python code:
>>> repr('foo')
"'foo'"
>>> print(repr('foo'))
'foo'
Now, when you say, you want the result without those quotes, you have to think about what that actually means. You could easily format the result string yourself. For example like this:
return '({0}, {1}, {2})'.format(element, count, str(type(element)))
This will return a string that would look like the way you want.
However, by doing that, you also lose the information you had when you returned a tuple. Now, you just return a string that has no information about the actual source values. So you cannot take the count value out without parsing the string again.
So, think about what you want to do: Do you actually just want something nice to print, or do you actually want to get those three values individually as a return value to be able to use them for something else afterwards?
You could always consider printing the text in the desired format later, if you already have the return values as a tuple…
Btw.: Note that when not calling str(type(element)) but just type(element), you would get back a type element (instead of a string). And the repr() of a type element happens to be exactly what you would want to have. So as a quick fix, you could always get rid of that str() call there.
There will always be some quotes around it because it is a string!
If you want to return None when the string is "" then you could do this:
x = str(type(s))
return(element, count, x if x else None)

Why does a call to `str(someList)` sometimes create an "array" of spaces?

playerList contains two Player objects (with str attributes called, respectively, "a" and "b"), and Player implements __str__ and __repr__. When I concatenate str(playerList) onto another string, I expect the string to be appended by something of the form "[a, b]". Instead, the resulting string is appended by "[ , ]". What mistake am I making that gives this result?
Here's what I wrote
prompt = "And then choose the opponent you would like to attack from " + str(playerList)
def __str__ (self):
return self.name
def __repr__ (self):
return str()
What I get on stdout:
"And then choose the opponent you would like to attack from [, ]"
What I want:
"And then choose the opponent you would like to attack from [a,b]"
Your __repr__ method returns an empty string:
def __repr__(self):
return str()
str() with no arguments is an empty string:
>>> str()
''
If you wanted to call __str__ do so directly, or pass self to str():
return self.__str__()
or
return str(self)
Note that converting a list to a string will include all strings in that list as their representation; the output of repr(stringobject), which uses the same notation you'd use when creating such a string. The list ['a', 'b'] is going to be converted to a string using exactly that notation:
>>> l = ['a', 'b']
>>> l
['a', 'b']
>>> str(l)
"['a', 'b']"
>>> print str(l)
['a', 'b']
If you really wanted to include those strings without quotes, you'll need to do your own formatting:
>>> '[{}]'.format(', '.join([str(elem) for elem in l]))
'[a, b]'
>>> print '[{}]'.format(', '.join([str(elem) for elem in l]))
[a, b]

Value Incrementation Confusion

Hey am new to python development and i am fully filled with a lots of doubts since am a newbie.Suppose
s = 'something'
for something in s:
something = something + 1
print something
I know here something act as an index and it would print out the whole elements in s.
And in
s = 'something'
for something in s:
s[something] = s[something] + 1
print something
I didnt understand the correct meaning of the second part of the code..Is it possible in python??..
'
Sorry for low grade question and any help would be appreciated ..
When you loop through a string like this:
for c in 'something':
print(c)
c does not act as an index, it acts as character of the string, so the output would be:
s
o
m
e
t
h
i
n
g
If you want to loop through the indices you can do:
s = 'something'
for i in range(len(s)):
print(i)
And the output would be:
0
1
2
3
4
5
6
7
8
You can access a character from the string by indexing like this:
s = 'something'
for i in range(len(s)):
print(s[i])
And the output of that would be:
s
o
m
e
t
h
i
n
g
If you want to loop through a string so that you get the characters as well as the indices, you can use the enumerate() function:
s = 'something'
for i, c in enumerate(s):
print(i, c)
The output:
0 s
1 o
2 m
3 e
4 t
5 h
6 i
7 n
8 g
Note that strings are immutable, so you can't change them:
>>> s = 'something'
>>> s[0] = 'a'
TypeError: 'str' object does not support item assignment
When you do string concatenation, you are not actually changing the string, you are creating a new one.
EDIT 1
Strings have methods that can be called on them to do certain tasks, such as the .split() method:
>>> s = 'something'
>>> s.split('e')
['som', 'thing']
They also have some special methods like __getitem__. The following two are equivalent:
>>> s = 'something'
>>> s[0]
's'
>>> s.__getitem__(0)
's'
Other sequences like lists are mutable, so they also have a __setitem__ method:
>>> s = ['s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g']
>>> s[0] = 't'
>>> s
['t', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g']
>>> s.__setitem__(0, 's')
>>> s
['s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g']
EDIT 2
This is what happens when you try to do this s[something] = s[something] + 1:
>>> s = 'something'
>>> s[0] = s[0] + 1
TypeError: Can't convert 'int' object to str implicitly
The reason this happens is because s[0] is 's' so you are trying to add a number to a string, which doesn't make any sense. Then if you try and do s[something] = s[something] + 'a' you will get a TypeError because strings are immutable:
>>> s = 'something'
>>> s[0] = s[0] + 'a'
TypeError: 'str' object does not support item assignment
And this will definitely not work:
>>> s = 'something'
>>> s['a']
TypeError: string indices must be integers
s[something] = s[something] + 1 shouldn't work; string values are immutable.
Syntax like s += "foo" actually creates a new string value from s + "foo", then assigns it to s, releasing the original value of s to be garbage collected.
A key thing to remember about all variables in Python is that they're just references to values. There's no guarantee the values aren't pooled somewhere and have a copy-on-write semantic. Another example is that a like like x = 5 doesn't set x to 5, it creates (or otherwise obtains) the value 5 and sets x to refer to it.
For the most part this distinction really doesn't matter. In general, the Right Thing(TM) happens.
The code:
s = 'something'
for something in s:
# ...
treats s like a list of characters and sets something to each one in sequence through the loop. (This is unlike JavaScript.) If you want the indices and not just the characters, use:
s = 'something'
for i, something in enumerate(s):
# ...
so s[something] = s[something] + 1 is not possible in any situations ..right ?
It works fine for lists (e.g. [1, 2, 3]) and dictionaries (e.g. {"a": 1, "b": 2}). Just not for strings.
If you simply want to get a string where every character is replaced with the next one, first split the string with a list comprehension:
l = [c for c in s]
Replace each character with the next one:
l2 = [chr(ord(c) + 1) for c in l]
and glue them back together into a new string:
s2 = ''.join(l2)
Putting it all together:
s = 'something'
s2 = ''.join([chr(ord(c) + 1) for c in s])
The square brackets after a variable name invoke __getitem__ or __setitem__ on the variable, depending on the context. So for example, x[i] = x[i] + 1 is equivalent to x.__setitem__(i, x.__getitem__(i) + 1). You can read up about this in the docs here:
https://docs.python.org/2/reference/datamodel.html
There are several built-in types that implement one or both of these, for example strings, tuples, lists, and dictionaries. For the sequence types (strings, tuples, lists) the "item" being accessed or set is an index, so for example print 'hello'[0] would print h because you are getting the character at the first index in the list.
In this case, it looks like the second piece of code would actually cause an error because strings are not mutable. This means that string objects can't be modified, so they won't have __setitem__ implemented and s[something] = s[something] + 1 would fail. This could work with a mutable type like list or dict though, for example:
s = [1, 1, 1]
s[0] = s[0] + 1
# s is now [2, 1, 1]

Alternative to python string item assignment

What is the best / correct way to use item assignment for python string ?
i.e s = "ABCDEFGH" s[1] = 'a' s[-1]='b' ?
Normal way will throw : 'str' object does not support item assignment
Strings are immutable. That means you can't assign to them at all. You could use formatting:
>>> s = 'abc{0}efg'.format('d')
>>> s
'abcdefg'
Or concatenation:
>>> s = 'abc' + 'd' + 'efg'
>>> s
'abcdefg'
Or replacement (thanks Odomontois for reminding me):
>>> s = 'abc0efg'
>>> s.replace('0', 'd')
'abcdefg'
But keep in mind that all of these methods create copies of the string, rather than modifying it in-place. If you want in-place modification, you could use a bytearray -- though that will only work for plain ascii strings, as alexis points out.
>>> b = bytearray('abc0efg')
>>> b[3] = 'd'
>>> b
bytearray(b'abcdefg')
Or you could create a list of characters and manipulate that. This is probably the most efficient and correct way to do frequent, large-scale string manipulation:
>>> l = list('abc0efg')
>>> l[3] = 'd'
>>> l
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> ''.join(l)
'abcdefg'
And consider the re module for more complex operations.
String formatting and list manipulation are the two methods that are most likely to be correct and efficient IMO -- string formatting when only a few insertions are required, and list manipulation when you need to frequently update your string.
Since strings are "immutable", you get the effect of editing by constructing a modified version of the string and assigning it over the old value. If you want to replace or insert to a specific position in the string, the most array-like syntax is to use slices:
s = "ABCDEFGH"
s = s[:3] + 'd' + s[4:] # Change D to d at position 3
It's more likely that you want to replace a particular character or string with another. Do that with re, again collecting the result rather than modifying in place:
import re
s = "ABCDEFGH"
s = re.sub("DE", "--", s)
I guess this Object could help:
class Charray(list):
def __init__(self, mapping=[]):
"A character array."
if type(mapping) in [int, float, long]:
mapping = str(mapping)
list.__init__(self, mapping)
def __getslice__(self,i,j):
return Charray(list.__getslice__(self,i,j))
def __setitem__(self,i,x):
if type(x) <> str or len(x) > 1:
raise TypeError
else:
list.__setitem__(self,i,x)
def __repr__(self):
return "charray['%s']" % self
def __str__(self):
return "".join(self)
For example:
>>> carray = Charray("Stack Overflow")
>>> carray
charray['Stack Overflow']
>>> carray[:5]
charray['Stack']
>>> carray[-8:]
charray['Overflow']
>>> str(carray)
'Stack Overflow'
>>> carray[6] = 'z'
>>> carray
charray['Stack zverflow']
s = "ABCDEFGH" s[1] = 'a' s[-1]='b'
you can use like this
s=s[0:1]+'a'+s[2:]
this is very simple than other complex ways

Why doesn't list have safe "get" method like dictionary?

Why doesn't list have a safe "get" method like dictionary?
>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'
>>> l = [1]
>>> l[10]
IndexError: list index out of range
Ultimately it probably doesn't have a safe .get method because a dict is an associative collection (values are associated with names) where it is inefficient to check if a key is present (and return its value) without throwing an exception, while it is super trivial to avoid exceptions accessing list elements (as the len method is very fast). The .get method allows you to query the value associated with a name, not directly access the 37th item in the dictionary (which would be more like what you're asking of your list).
Of course, you can easily implement this yourself:
def safe_list_get (l, idx, default):
try:
return l[idx]
except IndexError:
return default
You could even monkeypatch it onto the __builtins__.list constructor in __main__, but that would be a less pervasive change since most code doesn't use it. If you just wanted to use this with lists created by your own code you could simply subclass list and add the get method.
This works if you want the first element, like my_list.get(0)
>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'
I know it's not exactly what you asked for but it might help others.
Probably because it just didn't make much sense for list semantics. However, you can easily create your own by subclassing.
class safelist(list):
def get(self, index, default=None):
try:
return self.__getitem__(index)
except IndexError:
return default
def _test():
l = safelist(range(10))
print l.get(20, "oops")
if __name__ == "__main__":
_test()
Instead of using .get, using like this should be ok for lists. Just a usage difference.
>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'
Credits to jose.angel.jimenez and Gus Bus.
For the "oneliner" fans…
If you want the first element of a list or if you want a default value if the list is empty try:
liste = ['a', 'b', 'c']
value = (liste[0:1] or ('default',))[0]
print(value)
returns a
and
liste = []
value = (liste[0:1] or ('default',))[0]
print(value)
returns default
Examples for other elements…
liste = ['a', 'b', 'c']
print(liste[0:1]) # returns ['a']
print(liste[1:2]) # returns ['b']
print(liste[2:3]) # returns ['c']
print(liste[3:4]) # returns []
With default fallback…
liste = ['a', 'b', 'c']
print((liste[0:1] or ('default',))[0]) # returns a
print((liste[1:2] or ('default',))[0]) # returns b
print((liste[2:3] or ('default',))[0]) # returns c
print((liste[3:4] or ('default',))[0]) # returns default
Possibly shorter:
liste = ['a', 'b', 'c']
value, = liste[:1] or ('default',)
print(value) # returns a
It looks like you need the comma before the equal sign, the equal sign and the latter parenthesis.
More general:
liste = ['a', 'b', 'c']
f = lambda l, x, d: l[x:x+1] and l[x] or d
print(f(liste, 0, 'default')) # returns a
print(f(liste, 1, 'default')) # returns b
print(f(liste, 2, 'default')) # returns c
print(f(liste, 3, 'default')) # returns default
Tested with Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
Try this:
>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'
A reasonable thing you can do is to convert the list into a dict and then access it with the get method:
>>> my_list = ['a', 'b', 'c', 'd', 'e']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
>>> my_dict.get(2)
'c'
>>> my_dict.get(10, 'N/A')
So I did some more research into this and it turns out there isn't anything specific for this. I got excited when I found list.index(value), it returns the index of a specified item, but there isn't anything for getting the value at a specific index. So if you don't want to use the safe_list_get solution which I think is pretty good. Here are some 1 liner if statements that can get the job done for you depending on the scenario:
>>> x = [1, 2, 3]
>>> el = x[4] if len(x) > 4 else 'No'
>>> el
'No'
You can also use None instead of 'No', which makes more sense.:
>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None
Also if you want to just get the first or last item in the list, this works
end_el = x[-1] if x else None
You can also make these into functions but I still liked the IndexError exception solution. I experimented with a dummied down version of the safe_list_get solution and made it a bit simpler (no default):
def list_get(l, i):
try:
return l[i]
except IndexError:
return None
Haven't benchmarked to see what is fastest.
Dictionaries are for look ups. It makes sense to ask if an entry exists or not. Lists are usually iterated. It isn't common to ask if L[10] exists but rather if the length of L is 11.
If you
want a one liner,
prefer not having try / except in your happy code path where you needn't, and
want the default value to be optional,
you can use this:
list_get = lambda l, x, d=None: d if not l[x:x+1] else l[x]
Usage looks like:
>>> list_get(['foo'], 4) == None
True
>>> list_get(['hootenanny'], 4, 'ho down!')
'ho down!'
>>> list_get([''], 0)
''
For small index values you can implement
my_list.get(index, default)
as
(my_list + [default] * (index + 1))[index]
If you know in advance what index is then this can be simplified, for example if you knew it was 1 then you could do
(my_list + [default, default])[index]
Because lists are forward packed the only fail case we need to worry about is running off the end of the list. This approach pads the end of the list with enough defaults to guarantee that index is covered.
This isn't an extremely general-purpose solution, but I had a case where I expected a list of length 3 to 5 (with a guarding if), and I was breaking out the values to named variables. A simple and concise way I found for this involved:
foo = (argv + [None, None])[3]
bar = (argv + [None, None])[4]
Now foo and bar are either the 4th and 5th values in the list, or None if there weren't that many values.
Your usecase is basically only relevant for when doing arrays and matrixes of a fixed length, so that you know how long they are before hand. In that case you typically also create them before hand filling them up with None or 0, so that in fact any index you will use already exists.
You could say this: I need .get() on dictionaries quite often. After ten years as a full time programmer I don't think I have ever needed it on a list. :)

Categories