我正在尝试遍历列表, workerl 我定义的类的实例 worker ,并基于其中一个类属性 isemployed ,抓住其中的5个并在其上调用一个函数, fire()。我尝试了很多不同的方法,但是我要么陷入无休止的循环中,要么得到错误的值。
请让我知道我做错了什么,代码如下,我需要帮助的部分用粗体评论,但其他提示也很受欢迎。谢谢!
from random import choice
import sys
class Population:
"""total population of workers"""
workerl = []
workers = 0
g_rate = 1
y = 0
ui = 0
c = 5
def __init__(self, ui, workers):
# probability of a worker becoming unemployed
# low in booms, high in recessions, could be a proxy for i
self.ui = ui
self.workers = workers
self.workerl = []
for i in range(workers):
x = Worker()
self.workerl.append(x)
for i in range(workers / 10.):
self.workerl[i].fire()
def countEmployed(self):
"""displays number of employed workers in a population"""
employed = 0
for worker in self.workerl:
if worker.isemployed == True:
employed = employed + 1
return employed
def countUnemployed(self):
"""displays number of unemployed workers in a population"""
unemployed = 0
for worker in self.workerl:
if worker.isemployed == False:
unemployed = unemployed + 1
return unemployed
def employedl(self):
employedl = []
for worker in self.workerl:
if worker.isemployed:
employedl.append(worker)
return employedl
def unemployedl(self):
unemployedl = []
for worker in self.workerl:
if worker.isemployed == False:
unemployedl.append(worker)
return unemployedl
def lookingl(self):
lookingl = []
for worker in self.workerl:
if worker.islooking:
lookingl.append(worker)
return employedl
def advance(self, time):
"""advances the population units of time"""
# updates assets
for worker in self.workerl:
if worker.isemployed == True:
worker.assets = worker.assets + worker.salary
else:
worker.assets = worker.assets + self.ui - self.c
#calculates current y
tmp_y = 0
for worker in self.workerl:
tmp_y = worker.assets + tmp_y
self.y = tmp_y
# fires some workers, random turnover
# THIS IS THE PART I NEED HELP WITH
# as discussed above, i need to pick 5 workers from workerl
# where isemployed == True
# and then call their fire() method
# makes job search decisions for unemployed
jobs = self.y / 10
jobseekers = 0
for worker in self.workerl:
if worker.islooking:
jobseekers =+ 1
if jobs/jobseekers > 1:
d = 1
elif jobs/jobseekers < 0:
d = 0
else:
d = jobs / jobseekers
for worker in self.workerl:
if worker.isemployed == False:
if ((d * 5 + (1 - d) * (self.ui - self.c)) > self.ui):
worker.look()
else:
worker.unlook()
# hires some workers
jobcount = jobs
if d == 1:
for worker in self.workerl:
if worker.islooking:
worker.hire()
elif d == 0:
pass
else:
for i in range(jobs):
if self.workerl[i].islooking:
self.workerl[i].hire()
#calculates growth rate, updates y
tmp2_y = 0
for worker in self.workerl:
tmp2_y = worker.assets + tmp2_y
self.g_rate = (tmp_y / self.y) + 1.
self.y = tmp_y
# population as an array of workers
class Worker:
"""a worker in a population"""
isemployed = True
islooking = False
assets = 0
salary = choice(range(10))
def fire(self):
self.isemployed = False
self.islooking = True
def hire(self):
self.isemployed = True
self.islooking = False
def look(self):
self.islooking = True
def unlook(self):
self.islooking = False
def main():
x = Population(int(sys.argv[1]), int(sys.argv[2]))
x.advance(1)
print x.countEmployed()
print x.countUnemployed()
print x.y
main()
答案 0 :(得分:0)
您正在寻找的是random.choice功能。它允许您从列表中选择随机选择的值。以下是它的工作原理:
class Population:
employee_list = []
...
# Create a set that will contain the unique indices of newly fired employees
fired_indices = set()
# Keep count of how many we have fired
fired_count = 0
while fired_count < 5:
# Because we are using index numbers for bookkeeping, we need to chose from
# the list of indexes not the list of employees
# The xrange is much more efficient if we have large lists
i = random.choice( xrange( len( employee_list ) ) )
# Selection criteria -> employed and not already fired in *this* round
if employee_list[i].employed and i not in fired_indices:
employee_list[i].employed = false
fired_indices.add( i )
fired_count += 1
这种方法的问题在于可以多次选择同一个工人(我认为你不想这样做),并且必须继续拒绝他作为一个有效的选择。您可能还会选择许多已经失业的工人,然后再找到不工作的工人。这些冗余会给选择循环增加额外的迭代,从而导致效率下降。
如果您在Population类中有两个单独的列表,这可以更有效地工作。你可以有一份就业工人名单和一份失业人员名单。如果您保留两个单独的列表,那么选择将非常简单。您可以避免选择已经失业的工人,并且可以使用random.sample从列表中选择k个唯一选择。这是一个例子:
class Population:
employed_list = []
unemployed_list = []
...
fired_indices = random.sample( xrange( len( employed_list ) ) )
for i in fired_indices:
fired_employee = employed_list.pop( i )
unemployed_list.append( fired_employee )
...
当然,如果你是列表推导的粉丝,你可以一行完成:
unemployed_list.extend( [ employed_list.pop( i ) for i in random.sample( xrange( len( employed_list ) ) ] )
希望这会有所帮助。在模块上使用dir()方法来查看它们是否具有您可能正在寻找的有用内容总是一个好主意:
>>> dir( random )
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', 'WichmannHill', '_BuiltinMethodType', '_MethodType', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '_acos', '_cos', '_e', '_exp', '_hexlify', '_inst', '_log', '_pi', '_random', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', '**choice**', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'jumpahead', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', '**sample**', 'seed', 'setstate', 'shuffle', 'uniform', 'vonmisesvariate', 'weibullvariate']
答案 1 :(得分:0)
你选择这样的随机样本:
import random
for worker in random.sample(self.employedl(), k=5): # pick 5
worker.fire()
顺便说一下,你可以用列表推导来减少你的代码,即:
def employedl(self):
return [worker for worker in self.workerl if worker.isemployed]