簡體   English   中英

ValueError:list.remove(x):x不在列表中(但它是!)

[英]ValueError: list.remove(x): x not in list (But it is!)

我正在研究O'Reilly的書“探索R和Ruby中的日常事物”,並試圖用Python重寫所有Ruby代碼。 第一個示例是一個模型,用於計算建築物需要多少個浴室。 我正在使用的代碼如下。

但是,當我運行example34.py文件時,出現以下錯誤:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "example34.py", line 39, in <module>
    new_restroom.enter(queue.pop(0))
  File "restroom.py", line 21, in enter
    unoccupied_facilities[0].occupy(person)
  File "restroom.py", line 46, in occupy
    Person.population.remove(person)
ValueError: list.remove(x): x not in list

我是Python的新手,所以我懷疑這是與變量范圍或Python的某些未知屬性有關的問題。 奇怪的是,它打破后,運行person in Person.population返回True,命令Person.population.remove(person)成功地除去人的實例,所以這個人顯然在列表中。

有任何想法嗎?

example34.py:

from restroom import *  # imports the model

# Simulation script 1

frequency = 3  # how many times a person goes to the restroom within the period
facilities_per_restroom = 3
use_duration = 1  # measured in ticks
population_range = range(100, 110, 10)  # Creates an array from 10 to 600 by 10s

# Stores data for printing later
data = {}

# Loops for each population size in the above range
for population_size in population_range:
    # Starts each loop fresh
    Person.population = []
    # Creates the population of people
    Person.population = [
        Person(frequency, use_duration) for
        each in range(population_size)]
    # Creates the key for this population size
    data[population_size] = []
    #Create the restroom
    new_restroom = Restroom(facilities_per_restroom)
    # Iterate over the period
    for each in range(duration):
        # Records the queue size at this tick
        data[population_size].append(len(new_restroom.queue))
        # Create a temporary queue so that we can sort people between the
        # facilities and the restroom queue for this "tick"
        queue = list(new_restroom.queue)
        # Clear the queue to prepare for sorting
        new_restroom.queue = []
        # Take each person from the temporary queue and try adding
        # them a facility
        while bool(queue):
            # De-queue the person at the front of the line, place in an
            # unoccupied facility or, if none, back to the restroom queue
            new_restroom.enter(queue.pop(0))

        # for each person in the population, check if they need to go
        for person in Person.population:
            if person.need_to_go():
                new_restroom.enter(person)
        new_restroom.tick()

print(data)

restroom.py:

from random import randint
duration = 9 * 60  # minutes


class Restroom(object):

    def __init__(self, facilities_per_restroom=3):
        # Start with an empty queue
        self.queue = []
        # The facilities in this restroom
        self.facilities = []
        # Creates the facilities
        self.facilities = ([Facility() for each in
                            range(facilities_per_restroom)])

    def enter(self, person):
        unoccupied_facilities = [
            facility for facility in self.facilities
            if facility.occupied() == 0]
        if unoccupied_facilities:
            unoccupied_facilities[0].occupy(person)
        else:
            self.queue.append(person)
            Person.population.remove(person)

    def tick(self):
        [each.tick() for each in self.facilities]
        [f.tick for f in self.facilities]


class Facility(object):
    def __init__(self):
        self.occupier = None  # no one is occupying this facility at the start
        self.duration = 0  # how long the facility has been occupied

    def occupied(self):
        return 1 if (self.occupier is not None) else 0

    def occupy(self, person):
        # if the facility is unoccupied, add the person. Else, return false.
        if not self.occupied():
            self.occupier = person
            self.duration = 1
            #remove the person from the population since
            # they're in a facility now
            Person.population.remove(person)
            return 1  # return true
        else:
            return 0  # Return false

    def vacate(self):
        Person.population.append(self.occupier)
        self.occupier = None

    def tick(self):
        # if the facility is occupied and they've been
        # there longer than the use duration, have them leave
        if self.occupied() and (self.duration > self.occupier.use_duration):
            self.vacate()
            self.duration = 0
        elif self.occupied():
            # If occupied, increment the time
            self.duration += 1


class Person(object):

    #Class variable for storing the entire population
    population = []

    def __init__(self, frequency=4, use_duration=1):
        # Number of times a person uses the facilities per day
        self.frequency = frequency
        # How long each person uses the facilities
        self.use_duration = use_duration

    def need_to_go(self):

        return randint(1, duration) <= self.frequency

您在代碼中遇到了一個簡單的錯誤。

洗手間有一個隊列,其中添加了Person對象,沒有可用的停頓。

邏輯是:

def enter(self, person):
    unoccupied_facilities = [
        facility for facility in self.facilities
        if facility.occupied() == 0]
    if unoccupied_facilities:
        unoccupied_facilities[0].occupy(person)
    else:
        self.queue.append(person)
        Person.population.remove(person)

請注意, .occupy()將從Person.population列表中刪除一個人,或者如果沒有可用的檔位,則將該人添加到self.queue將從Person.population刪除。

然后, example34代碼處理該隊列:

queue = list(new_restroom.queue)
# Clear the queue to prepare for sorting
new_restroom.queue = []
# Take each person from the temporary queue and try adding
# them a facility
while bool(queue):
    # De-queue the person at the front of the line, place in an
    # unoccupied facility or, if none, back to the restroom queue
    new_restroom.enter(queue.pop(0))

因此人們被從隊列中帶走,然后重新進入洗手間。 如果任何攤位都空了, unoccupied_facilities[0].occupy(person)嘗試再次Person.population刪除該人。 在這一點上出現了例外,因為該人絕對不再在該列表中。

解決方案是不要在兩個不同的位置將person從總體中移除,或者在處理隊列時將人員重新添加到總體中。

將隊列處理代碼更改為:

while bool(queue):
    # De-queue the person at the front of the line, place in an
    # unoccupied facility or, if none, back to the restroom queue
    person = queue.pop(0)
    Person.population.append(person)
    new_restroom.enter(person)

解決此問題,例如:

$ python2.7 example34.py 
{100: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0]}

但是僅通過查看stacktrace即可清楚地表明ValueError: list.remove(x): x not in list person ,你正試圖刪除不在列表中。 因此,您需要捕獲此異常並進行適當處理-

#some loop, get the person to be removed
...
try:
    Person.population.remove(person)
except ValueError:
    pass #silently continue. Either that person is already removed or is not present.
...

當然,這段代碼並不完整。 它只是強調了try: except ValueError:的使用, try: except ValueError:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM