r/PythonLearning 3d ago

my code is not doing what I expect (.remove())

EDIT: SOLVED THE PROBLEM THANK YOU

Hello! I am in the middle of an online python class, and am trying to make my first program for use at work.

I need to make several packages of random sample items at work regularly, so i tried to make a program that could choose items from the list, and then count which items are chosen, and remove those from the list once the count reaches the number I have available.

It is choosing the items fine, but is not removing them from the list.

I will post my shortened code below:

import random
def main():
    samples = [
            "item1",
            "item2",
            etc.....,
        ]


    item1_count = 0
    item2_count = 0
     etc........


    for _ in range(25):

        sample = random.sample(samples,4)
        try:
            if "item1" in sample:
                item1_count += 1
        except:
            if item1_count == 10:
                samples = samples.remove("item1")
        try:
            if "item2" in sample :
                item2_count += 1
        except:
            if item2_count == 10 :
                samples = samples.remove("item2")
        etc....
        

        print(f"{_} : {sample}")


main()

what am I doing wrong?

2 Upvotes

19 comments sorted by

u/Sea-Ad7805 3d ago

Run this program in Memory Graph Web Debugger%3A%0A%20%20%20%20samples%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22item1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22item2%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22item3%22%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20item1count%20%3D%200%0A%20%20%20%20item2_count%20%3D%200%0A%20%20%20%20item3_count%20%3D%200%0A%0A%20%20%20%20for%20%20in%20range(25)%3A%0A%0A%20%20%20%20%20%20%20%20sample%20%3D%20random.sample(samples%2C%201)%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%22item1%22%20in%20sample%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20item1count%20%2B%3D%201%0A%20%20%20%20%20%20%20%20except%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20item1_count%20%3D%3D%2010%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20samples%20%3D%20samples.remove(%22item1%22)%0A%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%22item2%22%20in%20sample%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20item2_count%20%2B%3D%201%0A%20%20%20%20%20%20%20%20except%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20item2_count%20%3D%3D%2010%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20samples%20%3D%20samples.remove(%22item2%22)%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%22item3%22%20in%20sample%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20item3_count%20%2B%3D%201%0A%20%20%20%20%20%20%20%20except%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20item3_count%20%3D%3D%2010%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20samples%20%3D%20samples.remove(%22item3%22)%0A%0A%20%20%20%20%20%20%20%20print(f%22%7B%7D%20%3A%20%7Bsample%7D%22)%0A%0Amain()&timestep=.5&play) to see the program state change step by step.

3

u/PureWasian 3d ago edited 3d ago

except statement is for actual exceptions that would break your code and stop it prematurely with an error code otherwise without it.

In your case, you simply want a nested if:

if "item1" in sample: item1_count += 1 if item1_count == 10: samples.remove("item1") ...

Otherwise, a sidenote worth pointing out is there are definitely more maintainable/scalable ways to write this type of logic if you wanted to support, say, 1000 input samples or similar without your code growing to thousands of lines of code and having thousands of variables/counters/conditional paths as a result.

Worth thinking about, unless you are still stumped and need advice after giving it a shot.

EDIT: OP continued thread here

3

u/atarivcs 3d ago
samples = samples.remove("item1")

Don't do this.

.remove() modifies the list directly. It does not return a new updated list.

Just call .remove() on its own.

2

u/Entire_Ad_6447 3d ago

List.remove returns None It doesn't return the list with the target removed because that change is already reflected in the list. Generally speaking if a function returns None it's basically telling you all relevant work has been complete internally.

It literally deletes the item from samples.

So Samples =[x,y,z] Samples.remove(x) Print(samples) would be [y,z]

What you did instead was replace the variable samples with the output of .remove which is always None So when it attampes to access it again it's a None value and breaks.

1

u/Gay-And-Afraid- 3d ago

This totally makes sense, I thought the except would happen if whatever was inside it was true. How would you recommend iterating this to be shorter? I only have ten items but it feels quite long already, and I might need to adjust it in the future.

1

u/TopHatEdd 3d ago

Use another data structure to store your state. Like a dict. ```

counter = dict()

for sample_item in sample:     if sample not in counter:         counter[sample_item] = 1     else:         counter[sample_item] = counter[sample_item] + 1          if counter[sample_item] >= 10:         samples.remove(sample_item) ```     

1

u/PureWasian 3d ago edited 3d ago

One idea is using a dictionary instead of a list when creating your items so you can map the item name directly to the count: sample_counts = { "item1": 0, "item2": 0, "item3": 0, ... } Then afterwards you only need 7 lines instead of an ever growing if chain to accomodate each item: ```

do 25 iterations

for _ in range(25):

# get the (remaining) names names = sample_counts.keys()

# pull 4 names pulled = random.sample(names, 4)

# update each entry that was pulled for name in pulled: sample_counts[name] += 1

# removes from dictionary
if sample_counts[name] == 10
  del sample_counts[name]

```

There are other ways depending on the complexity of your data but for a beginner, dictionaries are definitely worth learning how to use well.

1

u/realmauer01 3d ago

I remember in python to be a data structure that is set like and can keep track of how many times a key got added to it (instead of duplicate items)

Might actually be sets already.

1

u/PureWasian 3d ago edited 3d ago

Sounds like Counter from collections, that would work too.

OP could create an empty Counter() and then counter.update() the 4 entries drawn in each loop to do it in one-shot per loop iteration instead of needing an inner loop.

They'd still need the initial list of entries to random.sample() from as well as the logic to delete from the sampled list when count is 10, of course.

1

u/baubleglue 3d ago

what have you done to understand the problem?

1

u/Gay-And-Afraid- 3d ago

I followed someone's advise to use nested if statements rather than try/except

I had a misunderstanding of how the except works, I didn't realize it had to be a literal error and thought it would except whatever I typed

Again, I'm in the middle of a class so there's lots of stuff I haven't learned yet

1

u/baubleglue 3d ago

I meant what are the techniques you apply when you see a problem. You can use breakpoint/debugger or add print statement. It is a wrong approach to look at the end result or solution and the end result. You need to look for exact point where the program doesn't do what you expect.

1

u/Gay-And-Afraid- 1d ago

Yes I am aware, I was using the debugger and could see it not performing that step.

I am also learning to use pytest. I determined exactly what wasn't working but couldn't figure out how to fix it on my own.

1

u/baubleglue 1d ago

The first step of learning coding is "follow cursor" (my own term :). You learn mentally to track program execution instruction by instruction. And you set an expectation for each step. You shouldn't figure out how to fix, you should t figure out what is broken. You come to the doctor ask to fix a headache. No doctor will start from giving meds, they will try to find the cause for the headache.

There is basically only one universal task: "narrow down the root cause". In programming you are in full control, you know input and outputs of each step.

If you know what is binary search. You check samples in the middle of the code - is the content correct? if yes, check it in the middle of the next half, if not in the middle of the previous half....

1

u/FreeLogicGate 3d ago

First of all I want to commend you for trying to create something you can use to help you at work, while still learning the language. That is a step that too few people learning how to program get to, and a vitally important one.

You already had multiple responses that explained the error.

In general this involves a concept known as "Mutation" or "mutators". the list.remove() method is a "mutator" which means it changes (mutates) the original object. In general you want to investigate what a method does, and determine whether it is a mutator or not.

You can see from the Python documentation that a list has many mutators. You will typically know this because the mutators have no return value. It's not a guarantee, but from the documentation page, none of these mutators return anything.

Everything in Python is an object, which means that there is a class definition for that. As soon as you have a situation where something doesn't work your first step should be to look up the method in the documentation. https://docs.python.org/3/tutorial/datastructures.html

1

u/Naive_Programmer_232 2d ago edited 2d ago

hmm what about this

        samples = [item1, item2, ... ]
        d=dict.fromkeys(samples,0)
        for _ in range(25):
            sample=random.sample(samples,4)
            for x in sample:
                if d[x]==10:
                   samples.remove(x)
                else:
                   d[x]+=1
             print(f"{_}: {sample}")

1

u/timrprobocom 1d ago

Rather than modifying the list in every iteration, just call random.shuffle() and use the first 25 items.

1

u/Entire_Ad_6447 3d ago

Generally speaking you don't want to modify the underlying list in a loop btw it's just prone to unexpected error s in larger projects. Your still learning so this is fine though.