Packing values back in tuple in python - python

I am working on a project where I got some data back in the form of a tuple, since a lot of it wasn't really needed I unpacked it and took what I needed, I need to make a new tuple with it how can I pack it back to original state within the tuple again ?
example code is :
name,*unused,amount=(name,age,address,email,contact,amount)
#this is how data gets unpacked
name=name
amount=amount
unused=['age','address','email','contact']
when I try packing it again using the tuple itself it becomes
data=(name,['age','address','email','contact'],amount)
is there any way to pack it back as the original state, as of now I'm manually unpacking the list and making the tuple again and want to avoid use of this extra function, looking for an internal way of doing it .

If I understand your question correctly, you are looking for this?. You can use * operator to unpack the the list elements
>>> first, *middle, last = (1, 2, 3, 4, 5)
>>> first
1
>>> middle
[2, 3, 4]
>>> last
5
>>> (first, *middle, last)
(1, 2, 3, 4, 5)

Related

after4 - Simple python task (index and list issues)

this is my first time asking a question on stack overflow. It has been really valuable to me while I have been learning python 2.7
The question is as follows:
"Given a non-empty list numlist of ints, write a function after4(numlist) that returns a new list containing the elements from the original numlist that come after the last 4 in the original numlist. The numlist will contain at least one 4.
after4([2, 4, 1, 2]) → [1, 2]
after4([4, 1, 4, 2]) → [2]
after4([4, 4, 1, 2, 3]) → [1, 2, 3]"
I believed the question to be rather simple but I just can seem to get the code right for what I had planned in my head.
def after4(numlist):
"""
Given a list of numbers, will print all numbers after the last 4
:param x: list - list of numbers including the 4
:return: list - New list of all numbers after the last 4
"""
indices = [i for i, x in enumerate(numlist) if x == 4]
index = max(indices)
print x[index:]
But I keep getting this error and I'm not sure how to work around it.
'int' object has no attribute 'getitem'" (the error is on the final line of the code "print x[index:]")
Thank you in advance.
You use the name x for two different purposes: as the list parameter for the function after4() and as an integer in the list comprehension for the variable indices.
The interpreter thinks you mean the integer one in the last line, but you mean the list parameter one. Change one of those names to a different name and see what happens.
You should use more descriptive variable names from now on. For example, instead of using x for the list parameter, use something like number_list, which makes it clear just what it is. Keep short names like x for mathematical parameters (such as math.sin(x)) and for list comprehensions.
Sorry, previous implementation was wrong. This is correct :)
def after4(x):
rev = list(reversed(x)) #rev = it's reversed list
start = len(x) - rev.index(4) #start = it's index of last 4, len(x) - length of list
print x[start:]
In method index(x, y):
x - searching element (here it's 4)
y - index from we want start searching, if we skip this argument it starts from index 0.

TypeError with functions

I am trying to define a function that returns a list without the first and last items in that list. However, I get this when I run the function: "TypeError: 'builtin_function_or_method' object does not support item deletion".
This is my code so far:
def middle(t):
"""returns a copy of a list with the first and last items removed
list -> list"""
t = input
del t[0]
del t[-1]
print(t)
Any help is appreciated.
t=input is assigning t to the function object input. You can't slice a function. t[1:-1] will return a new list with the first and last items removed.
You should delete the t = input line; that's assigning t to the built-in function input, which isn't an array and isn't what you want. Once you do that, you can use:
l = [0, 1, 2, 3, 4]
middle(l)
which will leave l = [1, 2, 3].
However, a better way of doing this is just to say
l = [0, 1, 2, 3, 4]
l2 = l[1:-1]
This leaves l2 as [1, 2, 3], as I assume you wanted.
If I were you, I'd go with something like
themiddlevalues = t[1:-1]
This works on any sort of sequence, and doesn't require a function. It's probably worth learning about python slice notation, as slices are important to numpy, etc. See http://codingbat.com/doc/python-strings.html, as slices work the same way across strings, lists, etc.

Where does the list assignment go?

A number of Python's list methods operate in place and return None (off the top of my head, insert, sort, reverse).
However, there is one behavior that frequently frustrates me. If I create a new list, which normally returns an object, and insert on it at the same time, the new list "disappears":
mytup = (0, 1, 2, 3, 4)
print mytup # (0, 1, 2, 3, 4)
mylist = list(mytup)
print mylist # [0, 1, 2, 3, 4]
newlist = list(mytup).insert(0, 10)
print newlist # None
So if I want to modify a tuple, it requires more lines:
newlist = list(mytup)
newlist.insert(0, 10)
print newlist # [10, 0, 1, 2, 3, 4]
So I have two questions:
Is it correct to say that when I call the list constructor, it returns the object, but when I call the list constructor with a method on it, the method "overrides" the return with None? Again, where does the list go?
Is there a way to insert into a tuple and return a list in one line? I am not trying to play code golf, I just don't think the two lines are logically different enough to merit separation.
insert,sort and reverse modify the list in-place and return None. And in your code you're actually storing that returned value in the newlist variable.
newlist = list(mytup).insert(0, 10)
And that newly created list(created on the fly) is garbage collected as there are no references to it any more.
In [151]: mytup = (0, 1, 2, 3, 4)
In [152]: lis=list(mytup) #create a new list object and add a reference to this new object
In [153]: newlist=lis.insert(0,10) #perform the insert operation on lis and store None
# in newlist
In [154]: print newlist
None
In [155]: print lis
[10, 0, 1, 2, 3, 4] #you can still access this list object with
#the help of `lis` variable.
The answer to your first question has already been given; you assign to the variable the result of the last function call, which is None. Here's the answer to your second question.
Rather than using insert, do something like this:
newlist = [10] + list(mytup)
It creates a new list containing the element to be inserted, appends it to the converted tuple and stores (a reference to) the resulting list.
This, of course, only works if you want to insert on either end.
If you need the new element to be inserted somewhere else, you have to slice the tuple, e.g. to insert after the third element in the tuple:
newlist = list(mytup[:3]) + [10] + list(mytup[3:])

good practice for string.partition in python

Sometime I write code like this:
a,temp,b = s.partition('-')
I just need to pick the first and 3rd elements. temp would never be used. Is there a better way to do this?
In other terms, is there a better way to pick distinct elements to make a new list?
For example, I want to make a new list using the elements 0,1,3,7 from the old list. The
code would be like this:
newlist = [oldlist[0],oldlist[1],oldlist[3],oldlist[7]]
It's pretty ugly, isn't it?
Be careful using
a, _, b = s.partition('-')
sometimes _ is use for internationalization (gettext), so you wouldn't want to accidentally overwrite it.
Usually I would do this for partition rather than creating a variable I don't need
a, b = s.partition('-')[::2]
and this in the general case
from operator import itemgetter
ig0137 = itemgetter(0, 1, 3, 7)
newlist = ig0137(oldlist)
The itemgetter is more efficient than a list comprehension if you are using it in a loop
For the first there's also this alternative:
a, b = s.partition('-')[::2]
For the latter, since there's no clear interval there is no way to do it too clean. But this might suit your needs:
newlist = [oldlist[k] for k in (0, 1, 3, 7)]
You can use Python's extended slicing feature to access a list periodically:
>>> a = range(10)
>>> # Pick every other element in a starting from a[1]
>>> b = a[1::2]
>>> print b
>>> [1, 3, 5, 7, 9]
Negative indexing works as you'd expect:
>>> c = a[-1::-2]
>>> print c
>>> [9, 7, 5, 3, 1]
For your case,
>>> a, b = s.partition('-')[::2]
the common practice in Python to pick 1st and 3rd values is:
a, _, b = s.partition('-')
And to pick specified elements in a list you can do :
newlist = [oldlist[k] for k in (0, 1, 3, 7)]
If you don't need to retain the middle field you can use split (and similarly rsplit) with the optional maxsplit parameter to limit the splits to the first (or last) match of the separator:
a, b = s.split('-', 1)
This avoids a throwaway temporary or additional slicing.
The only caveat is that with split, unlike partition, the original string is returned if the separator is not found. The attempt to unpack will fail as a result. The partition method always returns a 3-tuple.

Python list + list vs. list.append()

Today I spent about 20 minutes trying to figure out why
this worked as expected:
users_stories_dict[a] = s + [b]
but this would have a None value:
users_stories_dict[a] = s.append(b)
Anyone know why the append function does not return the new list? I'm looking for some sort of sensible reason this decision was made; it looks like a Python novice gotcha to me right now.
append works by actually modifying a list, and so all the magic is in side-effects. Accordingly, the result returned by append is None. In other words, what one wants is:
s.append(b)
and then:
users_stories_dict[a] = s
But, you've already figured that much out. As to why it was done this way, while I don't really know, my guess is that it might have something to do with a 0 (or false) exit value indicating that an operation proceeded normally, and by returning None for functions whose role is to modify their arguments in-place you report that the modification succeeded.
But I agree that it would be nice if it returned the modified list back. At least, Python's behavior is consistent across all such functions.
The append() method returns a None, because it modifies the list it self by adding the object appended as an element, while the + operator concatenates the two lists and return the resulting list
eg:
a = [1,2,3,4,5]
b = [6,7,8,9,0]
print a+b # returns a list made by concatenating the lists a and b
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print a.append(b) # Adds the list b as element at the end of the list a and returns None
>>> None
print a # the list a was modified during the last append call and has the list b as last element
>>> [1, 2, 3, 4, 5, [6, 7, 8, 9, 0]]
So as you can see the easiest way is just to add the two lists together as even if you append the list b to a using append() you will not get the result you want without additional work

Categories