1

I need to remove the first N elements from a list inside a function and I want the original list to be modified. What is a concise way to do this in Python?

Using a slice isn't working because the slice operation returns a separate reference to the list. In this example, I would like pkt to be [3,4,5] after calling the function.

>>>> def process_packet(packet, num_bytes):
         # ...
         packet = packet[num_bytes:len(packet)]
         print packet

>>> pkt = [1,2,3,4,5]
>>> process_packet(pkt, 2)
[3, 4, 5]
>>> print pkt
[1, 2, 3, 4, 5]
mksuth
  • 1,999
  • 4
  • 17
  • 24

5 Answers5

7

Simply use del to delete slices in place :)

>>> def process_packet(packet, num_bytes):
...     del packet[num_bytes:len(packet)]
... 
>>> a = range(10)
>>> process_packet(a,4)
>>> a
[0, 1, 2, 3]
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
  • With a docstring that says "THIS WILL MODIFY YOUR INPUT LIST" or similar... something subtle anyway. I'd also consider changing the name to `alter_` or similar to make it clearer... – Jon Clements Dec 10 '13 at 18:02
  • @JonClements Right, that's a good advice. I merely copied the bare minimum lines (& the name) from the code above. Hope he is doing that already in his production code. :) – UltraInstinct Dec 10 '13 at 18:05
  • 1
    Glad to learn about `del`. In this case `del packet[0:num_bytes]` would match the functionality in the original question. – mksuth Dec 10 '13 at 18:43
4

Use slice notation inside:

def process_packet(packet, num_bytes):
    packet[:] = packet[num_bytes:len(packet)]
    print packet

>>> pkt = [1,2,3,4,5]
>>> process_packet(pkt, 2)
[3, 4, 5]
>>> print pkt
[3, 4, 5]

Note that this works only if packet is a list or compatible iterable. The initial and final length of the list may be different, (larger and smaller, or vice verse are fine).

Pi Marillion
  • 4,465
  • 1
  • 19
  • 20
1

Add return packet at the end of your function.

And when you call the function call it like this: pkt = process_packet(pkt,2)

Lazybeem
  • 105
  • 6
  • OP doesn't want to make a new list, though I'm not sure if list mutation is a pythonic way to things. – MxLDevs Dec 10 '13 at 17:56
  • @MxyL they're not expressly saying they don't want a new list - more that they want the original to be updated... This does that in a round-about way :) (given the example anyway - were there other references to the list - it would invalidate my jovial response somewhat) – Jon Clements Dec 10 '13 at 17:57
  • @JonClements You're right, I assumed the "doesn't work, returns a separate reference" part implied "we don't want a copy" – MxLDevs Dec 10 '13 at 17:59
0

You can either use a deque from the collections module, and popleft num_bytes of times, or create a class that modifies self.pkt, or the simplest way is this:

def process_packet(pkt, num):
    return pkt[num:]

pkt = process_packet(pkt, 2)

Just return the packet, and reassign over it. This is probably what you would see the most to handle this sort of logic.

johannestaas
  • 1,175
  • 1
  • 9
  • 15
0

Read this answer to Python: How do I pass a variable by reference?. There you will find what you need to understand how Python pass arguments to functions. Later you will find the answer to your question by your self.

Community
  • 1
  • 1
Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60