How to turn a string lists into a lists? - python-3.x

There are other threads about turning strings inside a lists into different data types. I want to turn a string that is in the form of a lists into a lists. Like this: "[5,1,4,1]" = [5,1,4,1]
I need this because I am writing a program that requires the user to input a lists
Example of problem:
>>> x = input()
[3,4,1,5]
>>> x
'[3,4,1,5]'
>>> type(x)
<class 'str'>

If you mean evaluate python objects like this:
x = eval('[3,4,1,5]');
print (x);
print(type(x) is list)
[3, 4, 1, 5]
True
Use this with caution as it can execute anything user will input. Better use a parser to get native lists. Use JSON for input and parse it.

Use eval() for your purpose. eval() is used for converting code within a string to real code:
>>> mystring = '[3, 5, 1, 2, 3]'
>>> mylist = eval(mystring)
>>> mylist
[3, 5, 1, 2, 3]
>>> mystring = '{4: "hello", 2:"bye"}'
>>> eval(mystring)[4]
'hello'
>>>
Use exec() to actually run functions:
>>> while True:
... inp = raw_input('Enter your input: ')
... exec(inp)
...
Enter your input: print 'hello'
hello
Enter your input: x = 1
Enter your input: print x
1
Enter your input: import math
Enter your input: print math.sqrt(4)
2.0
In your scenario:
>>> x = input()
[3,4,1,5]
>>> x = eval(x)
>>> x
[3, 4, 1, 5]
>>> type(x)
<type 'list'>
>>>

Thanks for your input guys, but I would prefer not to eval() because it is unsafe.
Someone actually posted the answer that allowed me to solve this but then they deleted it. I am going to reposts that answer:
values = input("Enter values as lists here")
l1 = json.loads(values)

You can use ast.literal_eval for this purpose.
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the
following Python literal structures: strings, bytes, numbers, tuples,
lists, dicts, sets, booleans, and None.
This can be used for safely evaluating strings containing Python
expressions from untrusted sources without the need to parse the
values oneself.
>>> import ast
>>> val = ast.literal_eval('[1,2,3]')
>>> val
[1, 2, 3]
Just remember to check that it's actually a list:
>>> isinstance(val, list)
True

Related

I am learning python and I appreciate if someone explains why I got the following output regarding tuple. They seem kind of contradictory to me [duplicate]

Two variables in Python have the same id:
a = 10
b = 10
a is b
>>> True
If I take two lists:
a = [1, 2, 3]
b = [1, 2, 3]
a is b
>>> False
according to this link Senderle answered that immutable object references have the same id and mutable objects like lists have different ids.
So now according to his answer, tuples should have the same ids - meaning:
a = (1, 2, 3)
b = (1, 2, 3)
a is b
>>> False
Ideally, as tuples are not mutable, it should return True, but it is returning False!
What is the explanation?
Immutable objects don't have the same id, and as a matter of fact this is not true for any type of objects that you define separately. Generally speaking, every time you define an object in Python, you'll create a new object with a new identity. However, for the sake of optimization (mostly) there are some exceptions for small integers (between -5 and 256) and interned strings, with a special length --usually less than 20 characters--* which are singletons and have the same id (actually one object with multiple pointers). You can check this like following:
>>> 30 is (20 + 10)
True
>>> 300 is (200 + 100)
False
>>> 'aa' * 2 is 'a' * 4
True
>>> 'aa' * 20 is 'a' * 40
False
And for a custom object:
>>> class A:
... pass
...
>>> A() is A() # Every time you create an instance you'll have a new instance with new identity
False
Also note that the is operator will check the object's identity, not the value. If you want to check the value you should use ==:
>>> 300 == 3*100
True
And since there is no such optimizational or interning rule for tuples or any mutable type for that matter, if you define two same tuples in any size they'll get their own identities, hence different objects:
>>> a = (1,)
>>> b = (1,)
>>>
>>> a is b
False
It's also worth mentioning that rules of "singleton integers" and "interned strings" are true even when they've been defined within an iterator.
>>> a = (100, 700, 400)
>>>
>>> b = (100, 700, 400)
>>>
>>> a[0] is b[0]
True
>>> a[1] is b[1]
False
* A good and detailed article on this: http://guilload.com/python-string-interning/
Immutable != same object.*
An immutable object is simply an object whose state cannot be altered; and that is all. When a new object is created, a new address will be assigned to it. As such, checking if the addresses are equal with is will return False.
The fact that 1 is 1 or "a" is "a" returns True is due to integer caching and string interning performed by Python so do not let it confuse you; it is not related with the objects in question being mutable/immutable.
*Empty immutable objects do refer to the same object and their isness does return true, this is a special implementation specific case, though.
Take a look at this code:
>>> a = (1, 2, 3)
>>> b = (1, 2, 3)
>>> c = a
>>> id(a)
178153080L
>>> id(b)
178098040L
>>> id(c)
178153080L
In order to figure out why a is c is evaluated as True whereas a is b yields False I strongly recommend you to run step-by-step the snippet above in the Online Python Tutor. The graphical representation of the objects in memory will provide you with a deeper insight into this issue (I'm attaching a screenshot).
According to the documentation, immutables may have same id but it is not guaranteed that they do. Mutables always have different ids.
https://docs.python.org/3/reference/datamodel.html#objects-values-and-types
Types affect almost all aspects of object behavior. Even the importance of object identity is affected in some sense: for immutable types, operations that compute new values may actually return a reference to any existing object with the same type and value, while for mutable objects this is not allowed.
In previous versions of Python, tuples were assigned different IDs. (Pre 3.7)
As of Python 3.7+, two variables with the same tuple assigned may have the same id:
>>>a = (1, 2, 3)
>>>b = (1, 2, 3)
>>>a is b
True
Integers above 256 also have different ids:
>>>a = 123
>>>b = 123
>>>a is b
True
>>>
>>>a = 257
>>>b = 257
>>>a is b
False
Check below code..
tupils a and b are retaining their older references(ID) back when we have assigned their older values back. (BUT, THIS WILL NOT BE THE CASE WITH LISTS AS THEY ARE MUTABLE)
Initially a and b have same values ( (1,2) ), but they have difference IDs. After alteration to their values, when we reassign value (1,2) to a and b, they are now referencing to THEIR OWN same IDs (88264264 and 88283400 respectively).
>>> a = (1,2)
>>> b = (1,2)
>>> a , b
((1, 2), (1, 2))
>>> id(a)
88264264
>>> id(b)
88283400
>>> a = (3,4)
>>> b = (3,4)
>>> id(a)
88280008
>>> id(b)
88264328
>>> a = (1,2)
>>> b = (1,2)
>>> id(a)
88264264
>>> id(b)
88283400
>>> a , b
((1, 2), (1, 2))
>>> id(a) , id(b)
(88264264, 88283400)
>>>
**Check the link Why don't tuples get the same ID when assigned the same values?
also after reading this. Another case also been discussed here.

x[0], y[0], z[0] has the same memory address in cpython, but why a is not?

(env) λ python
Python 3.9.1 (tags/v3.9.1:1e5d33e, Dec 7 2020, 17:08:21) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> x = ["test t", 2, 3]
>>> y = x
>>> z = x[:]
>>> x, y, z
(['test t', 2, 3], ['test t', 2, 3], ['test t', 2, 3])
>>> id(x[0]), id(y[0]), id(z[0])
(2818792500464, 2818792500464, 2818792500464)
>>> a = "test t"
>>> id(a)
2818792500720
I know a little about the string constant pool and the string interning in python, why the python made the new defined string's memory address that contains special characters such as blank space different.
Strings in Python are immutable, that means that once a string is created, it can't be changed. When you create a string, and if you create same string and assign it to another variable they'll both be pointing to the same string/memory. For example,
>>> a = 'hi'
>>> b = 'hi'
>>> id(a)
437068484
>>> id(b)
437068484
This reuse of string objects is called interning in Python. The same strings have the same ids. But Python is not guaranteed to intern strings. If you create strings that are either not code object constants or contain characters outside of the letters + numbers + underscore range, you'll see the id() value not being reused.
We change the id of the given string as follows. We assign it to two different identifiers. The ids of these variables when found are different. This is because the given string contains characters other than alphabets, digits, and underscore.
>>> a = 'test_##$'
>>> b = 'test_##$'
>>> id(a)
962262086
>>> id(b)
917208009
Now looking your example:
x[0], y[0], z[0] are the same object, because when you create the x = ["test t", 2, 3] you started to pass the reference by alias to y and z
Now another example to clarify more:
Create a list with the same values, and create an alias for it, they will have the same id.
>>> a = [1,2,3]
>>> b = a
>>> id(a)
1984438821696
>>> id(b)
1984438821696
But when you create two equivalent lists, they are not identical as the previous.
>>> a = [1,2,3]
>>> b = [1,2,3]
>>> id(a)
1984438821696
>>> id(b)
1984438822336

How to multiply 2 input lists in python

Please help me understand how to code the following task in Python using input
Programming challenge description:
Write a short Python program that takes two arrays a and b of length n
storing int values, and returns the dot product of a and b. That is, it returns
an array c of length n such that c[i] = a[i] · b[i], for i = 0,...,n−1.
Test Input:
List1's input ==> 1 2 3
List2's input ==> 2 3 4
Expected Output: 2 6 12
Note that the dot product is defined in mathematics to be the sum of the elements of the vector c you want to build.
That said, here is a possibiliy using zip:
c = [x * y for x, y in zip(a, b)]
And the mathematical dot product would be:
sum(x * y for x, y in zip(a, b))
If the lists are read from the keyboard, they will be read as string, you have to convert them before applying the code above.
For instance:
a = [int(s) for s in input().split(",")]
b = [int(s) for s in input().split(",")]
c = [x * y for x, y in zip(a, b)]
Using for loops and appending
list_c = []
for a, b in zip(list_a, list_b):
list_c.append(a*b)
And now the same, but in the more compact list comprehension syntax
list_c = [a*b for a, b in zip(list_a, list_b)]
From iPython
>>> list_a = [1, 2, 3]
>>> list_b = [2, 3, 4]
>>> list_c = [a*b for a, b in zip(list_a, list_b)]
>>> list_c
[2, 6, 12]
The zip function packs the lists together, element-by-element:
>>> list(zip(list_a, list_b))
[(1, 2), (2, 3), (3, 4)]
And we use tuple unpacking to access the elements of each tuple.
From fetching the input and using map & lambda functions to provide the result. If you may want to print the result with spaces between (not as list), use the last line
list1, list2 = [], []
list1 = list(map(int, input().rstrip().split()))
list2 = list(map(int, input().rstrip().split()))
result_list = list(map(lambda x,y : x*y, list1, list2))
print(*result_list)
I came out with two solutions. Both or them are the ones that are expected in a Python introductory course:
#OPTION 1: We use the concatenation operator between lists.
def dot_product_noappend(list_a, list_b):
list_c = []
for i in range(len(list_a)):
list_c = list_c + [list_a[i]*list_b[i]]
return list_c
print(dot_product_noappend([1,2,3],[4,5,6])) #FUNCTION CALL TO SEE RESULT ON SCREEN
#OPTION 2: we use the append method
def dot_product_append(list_a, list_b):
list_c = []
for i in range(len(list_a)):
list_c.append(list_a[i]*list_b[i])
return list_c
print(dot_product_append([1,2,3],[4,5,6])) #FUNCTION CALL TO SEE RESULT ON SCREEN
Just note that the first method requires that you cast the product of integers to be a list before you can concatenate it to list_c. You do that by using braces ([[list_a[i]*list_b[i]] instead of list_a[i]*list_b[i]). Also note that braces are not necessary in the last method, because the append method does not require to pass a list as parameter.
I have added the two function calls with the values you provided, for you to see that it returns the correct result. Choose whatever function you like the most.

If I have duplicates in a list with brackets, what should I do

Suppose I have the following list:
m=[1,2,[1],1,2,[1]]
I wish to take away all duplicates. If it were not for the brackets inside the the list, then I could use:
m=list(set(m))
but when I do this, I get the error:
unhashable type 'set'.
What command will help me remove duplicates so that I could only be left with the list
m=[1,2,[1]]
Thank you
You can do something along these lines:
m=[1,2,[1],1,2,[1]]
seen=set()
nm=[]
for e in m:
try:
x={e}
x=e
except TypeError:
x=frozenset(e)
if x not in seen:
seen.add(x)
nm.append(e)
>>> nm
[1, 2, [1]]
From comments: This method preserves the order of the original list. If you want the numeric types in order first and the other types second, you can do:
sorted(nm, key=lambda e: 0 if isinstance(e, (int,float)) else 1)
The first step will be to convert the inner lists to tuples:
>> new_list = [tuple(i) if type(i) == list else i for i in m]
Then create a set to remove duplicates:
>> no_duplicates = set(new_list)
>> no_duplicates
{1, 2, (1,)}
and you can convert that into list if you wish.
For a more generic solution you can serialize each list item with pickle.dumps before passing them to set(), and then de-serialize the items with pickle.loads:
import pickle
m = list(map(pickle.loads, set(map(pickle.dumps, m))))
If you want the original order to be maintained, you can use a dict (which has become ordered since Python 3.6+) instead of a set:
import pickle
m = list(map(pickle.loads, {k: 1 for k in map(pickle.dumps, m)}))
Or if you need to be compatible with Python 3.5 or earlier versions, you can use collections.OrderedDict instead:
import pickle
from collections import OrderedDict
m = list(map(pickle.loads, OrderedDict((k, 1) for k in map(pickle.dumps, m))))
result = []
for i in m:
flag = True
for j in m:
if i == j:
flag = False
if flag:
result.append(i)
Result will be: [1,2,[1]]
There are ways to make this code shorter, but I'm writing it more verbosely for readability. Also, note that this method is O(n^2), so I wouldn't recommend for long lists. But benefits is the simplicity.
Simple Solution,
m=[1,2,[1],1,2,[1]]
l= []
for i in m:
if i not in l:
l.append(i)
print(l)
[1, 2, [1]]
[Program finished]

Pythonic and secure way to convert a list of integers to a string and vis-à-vis

I have a list of integers (e. g. [1, 2, 3] and want to convert them to one string (e. g. "1, 2, 3"). Later I will convert the string back into a list of integers.
Is my solution pythonic enough or is there a much easier way?
# init values
int_list = [1, 2, 3]
# list of integers to string
string = str(int_list)[1:-1]
# string to list of integers
int_list = [int(i) for i in string.split(',')]
By the way: My first approach was to do exec("int_list = [" + str + "]"). But using exec is absolutly not recommended.
Use map:
a = [1, 2, 3]
b = list(map(str, a))
c = list(map(int, b))
EDIT: if you want only one string, then
a = [1, 2, 3]
b = ",".join(map(str, a))
c = list(map(int, b.split(",")))
EDIT2: you can also use this to convert the map to a list. I don't like it too much, but it's an option:
c = [*map(int, b.split(","))]
# to string
a = [1,2,3]
s = repr(a)
print(s)
# from string
import ast
print(ast.literal_eval(s))
Unlike eval, literal_eval "can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself."

Resources