[英]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.