def check(val, list=[]):
list.append(val)
return list
list1=check("a")
list2=check("b",[])
list3=check("c")
If I run list1 and check the output it shows ["a"]
But, If I run list1, list2 and list3 in one
cell and check for list1 it shows ['a','c'], can someone please explain why is it so?
This is the right way to do this:
def check(val, values=None):
if values is None:
values = []
values.append(val)
return values
list1 = check("a")
list2 = check("b", [])
list3 = check("c")
Default argument values should not be mutable. You can find a good explanation here,
And list is a poor name for a variable, because list is a built-in type, as are str, set, dict.
It seems that list1 and list3 share same object.
You can try this:
def check(val, list=[]):
list.append(val)
print(hex(id(list)))
return list
list1=check("a")
list2=check("b")
list3=check("c")
print(list1)
print(list2)
print(list3)
Related
I stumbled upon a theoretical question about how python works, and it got me puzzled. I tried to understand exactly what happened but couldn't find the answer in google - I'm a beginner, so I don't even know the terminology to make the apropriate search.
On the following code, when calling the function it changes myList, while I only wanted to create a list2 which was a copy of list1 (myList).
myList = [1,2,3,4,5,(1,2),(3,4)]
def onlyTuples(list1):
list2 = list1 # here is my question
for index,e in enumerate(list2):
if type(list2[index]) is not tuple:
list2[index] = (list2[index],)
return(list2)
print(myList)
create_new_list = onlyTuples(myList) # triggered by this call
print(myList)
It's all good if I change list2 = list1 to list2 = list(list1) and myList won't be changed when calling the function, but why?
The same thing doesn't happen with something like this:
a = 6
b = a
b = 7
print(a)
Any light upon the question will be appreciated. Thanks!
In python lists are passed by reference, so when you pass list to a function you pass its address in the memory. list2 = list1 won't create a copy of the list, it will save in list2 the address saved in list1. so change of list2 will change list1, but the function in the class list doesn't save the address, it copy a sequence to a list
To make a copy of a list, use:
newList = myList.copy()
Here is some example code.
list1 = [['one','a'],['two','a'],['three','a'],['four','a']]
list2 = [['three','b'],['four','a'],['five','b']]
for l in list1:
if l not in list2:
print(l[0])
and the output from this code.
one
two
three
because ['four','a'] does indeed appear in both lists.
What I am trying to do is check if just the first item of each entry within the first list appears in the second list, I have tried variations of the following
list1 = [['one','a'],['two','a'],['three','a'],['four','a']]
list2 = [['three','b'],['four','a'],['five','b']]
for l in list1:
if l[0] not in list2:
print(l[0])
however, that code returns
one
two
three
four
though both 'three' and 'four' do appear in the second list.
I have used different methods before now to find the values that appear in only one of a pair of lists, then used that to make a master list that contains all possible values with no duplicates and I believe the same should be possible using this method but the syntax is a mystery to me. Where I am going wrong here?
You could use not any() and then you check specific requirements in the comprehension:
list1 = [['one','a'],['two','a'],['three','a'],['four','a']]
list2 = [['three','b'],['four','a'],['five','b']]
for l in list1:
if not any(l[0] == l2[0] for l2 in list2):
print(l[0])
# one
# two
You could also use sets if order doesn't matter:
list1 = [['one','a'],['two','a'],['three','a'],['four','a']]
list2 = [['three','b'],['four','a'],['five','b']]
set(l[0] for l in list1) - set(l2[0] for l2 in list2)
# {'one', 'two'}
you can use set operations
list1 = [['one','a'],['two','a'],['three','a'],['four','a']]
list2 = [['three','b'],['four','a'],['five','b']]
result = set(i[0] for i in list1) - set(i[0] for i in list2)
print(result)
# output {'one', 'two'}
I have a list of lists
list1 = [['a','b','c'],['m','n','o'],['x','y','z']]
Now, I want to check if all elements of any one of these 'sub-lists' are present in an incoming list called list2.
For example, if
list2 = ['a','c','e','b'] #Code would return True as a,b,c all from list1[0] match
list2 = ['a','c','m','x','e'] # False as all elements from any one sub-list do not match
list2 = ['g','h','i','x','y','z'] # True as all elements from list1[2] matched
I know that this can be done using a nested all within any python function. If list1 was not a nested list, I would have used
result = any(elem in list2 for elem in list1) # To check for any one
or
result = all(elem in list2 for elem in list1) # To check for all
However, I am at loss to do a nested any/all type of list comprehension. Any guidance would be appreciated.
You can do a combination of any and all:
list1 = [['a','b','c'],['m','n','o'],['x','y','z']]
def test(l1, l2):
return any(all(x in l2 for x in sub) for sub in l1)
print(test(list1, ['a','c','e','b']))
print(test(list1, ['a','c','m','x','e']))
print(test(list1, ['g','h','i','x','y','z']))
Output:
True
False
True
The test means: if all x's of any of the sublists are in list2.
Why not make list2 a set and use set.issuperset to see if all elements are in list2
list2 = {'g','h','i','x','y','z'}
print(any(list2.issuperset(elem) for elem in list1))
#True
You can even make this more simple using map although the comprehension is more readable
any(map(list2.issuperset, list1))
If you go this route I suggest not using list2 as the name to avoid confusion
Why the last part of my code doesn't work?
def common_elements(list1, list2):
#a list with common element
common_elements=[]
common_unique_elements=[]
for i in list1:
if i in list2:
common_elements.append(i)
#removing repeated elements
for i in common_elements:
if i not in common_unique_elements:
common_unique_elements.append(i)
#returning None for empty list
if len(common_elements)==0:
return None
return sorted(common_unique_elements)
There is absolutely no need of a second list just to hold unique common elements. You can do the check before you add to first list, thus avoiding the need of second list:
def common_elements(list1, list2):
common = []
for i in list1:
if i in list2 and i not in common:
common.append(i)
return None if not common else sorted(common)
list1 = ['a','b','b,','c']
list2 = ['f','b','e','a','a']
print(common_elements(list1, list2))
# ['a', 'b']
Avoid using function name for variables; can run into problems later.
list1 = ["name1", "info1", 10]
list2 = ["name2", "info2", 30]
list3 = ["name3", "info3", 50]
MASTERLIST = [list1, list2, list3]
def printer(lst):
print ("Available Lists:")
for x in range(len(lst)):
print (lst[x])[0]
This code is returning the "'NoneType' object is not subscriptable" error when I try and run
printer(MASTERLIST)
What did I do wrong?
The print() function returns None. You are trying to index None. You can not, because 'NoneType' object is not subscriptable.
Put the [0] inside the brackets. Now you're printing everything, and not just the first term.
The [0] needs to be inside the ).
Don't use list as a variable name for it shadows the builtin.
And there is no need to determine the length of the list. Just iterate over it.
def printer(data):
for element in data:
print(element[0])
Just an addendum: Looking at the contents of the inner lists I think they might be the wrong data structure. It looks like you want to use a dictionary instead.
Point A: Don't use list as a variable name
Point B: You don't need the [0] just
print(list[x])
The indexing e.g. [0] should occour inside of the print...
list1 = ["name1", "info1", 10]
list2 = ["name2", "info2", 30]
list3 = ["name3", "info3", 50]
def printer(*lists):
for _list in lists:
for ele in _list:
print(ele, end = ", ")
print()
printer(list1, list2, list3)