我正在阅读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)
成功删除了该人员实例,因此该人明显 在列表中。< / p>
有什么想法吗?
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
答案 0 :(得分:2)
您的代码中遇到了一个简单的错误。
休息室有一个队列,添加了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]}
答案 1 :(得分:0)
但是通过查看堆栈跟踪,它清楚地表明了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:
用法。