s = [1, 2, 3]
new_list = reverse(s)
print(new_list)
print(s)
#[3, 2, 1]
#[3, 2, 1]
#We should have passed it a copy of
#our list if we did not intend for
#our list to be modified
The code above called in-place method that the contents of requirement has changed.
The best code is below
#first method
def reverse(s):
s.reverse()
#second method
def reverse(s):
s2 = s.copy()
s2.reverse()
return s2
#Simple loop (definitly non-Pythonic)
cp = []
for e in s:
cp.append(e)
#List Comprehension (point to same memory address)
cp = [e for e in s]
#The copy method (elements point to same memory address, but cp is a new object)
cp = s.copy() #(not implement in ummutable types, such as tuples or stings)
#Slicing (always return a new object, elements point to the same memory address)
cp = s[0:len(s)]
#or, more simply
cp = s[:]
#list() (elements point to same memory address, but list2 is a new object)
list_2 = list(list_1) #can pass it any iterable and it will convert that ot a new list
#Note
tuple_2 = tuple(tuple_1)
#and
tuple_2 = tuple[:]
#No new tuple has created, it return the original tuple
s = [10, 20, 30]
cp = s.copy()
cp[0] = 100
#s [10, 20, 30]
#cp [100, 20, 30]
s = [[10, 20], [30, 40]]
cp = s.copy()
cp[0] = 'python'
#cp ['python', [30, 40]]
cp[1][0] = 100
#cp ['python', [100, 40]]
#s [[10, 20], [100, 40]]
s elements are immutable here.
a mutable element in s