将所有类实例存储在类字段中是否不好?
我在想,从面向对象编程的角度来看,这样做是否有什么问题:
class Foobar:
foobars = {}
def __init__(self, name, something):
self.name = name
self.something = something
Foobar.foobars[name] = self
Foobar('first', 42)
Foobar('second', 77)
for name in Foobar.foobars:
print name, Foobar.foobars[name]
编辑: 这是我现在正在使用的实际代码
from threading import Event
class Task:
ADDED, WAITING_FOR_DEPS, READY, IN_EXECUTION, DONE = range(5)
tasks = {}
def __init__(self, name, dep_names, job, ins, outs, uptodate, where):
self.name = name
self.dep_names = [dep_names] if isinstance(dep_names, str) else dep_names
self.job = job
self.where = where
self.done = Event()
self.status = Task.ADDED
self.jobs = []
# other stuff...
Task.tasks[name] = self
def set_done(self):
self.done.set()
self.status = Task.DONE
def wait_for_deps(self):
self.status = Task.WAITING_FOR_DEPS
for dep_name in self.dep_names:
Task.tasks[dep_name].done.wait()
self.status = Task.READY
def add_jobs_to_queues(self):
jobs = self.jobs
# a lot of stuff I trimmed here
for w in self.where: Queue.queues[w].put(jobs)
self.status = Task.IN_EXECUTION
def wait_for_jobs(self):
for j in self.jobs: j.wait()
#[...]
如你所见,我需要在wait_for_deps方法中访问一个包含所有实例的字典。用一个全局变量会不会更合理,而不是用类的字段?我可能在这里用错了方法,也许这些东西根本不应该放在一个方法里,但对我来说这样做是有道理的(我刚接触面向对象编程)
7 个回答
1
你为什么想这么做呢?
这段代码有几个问题。第一个问题是你需要手动删除实例——每个 Foobar
实例都会在 Foobar.foobars
中留下一个引用,这样垃圾回收器就无法清理它们。第二个问题是,这段代码在使用 copy
和 pickle
时会出问题。
不过,除了这些技术问题,这种设计感觉也不太对。对象实例的目的是隐藏状态,而你却让它们彼此可见。
4
我觉得这样做没有什么错误,但我真的看不出这样做有什么意义。为什么你需要在类里面保持一个全局变量,来存放所有实例的引用呢?客户自己完全可以简单地维护一个自己的实例列表。总的来说,这看起来有点像是变通的做法,而且也没必要,所以我建议你不要这样做。
如果你能更具体地说说你想要做什么,也许我们能找到更好的解决办法。
9
是的,这样做不好。它把一个实例和一堆实例搞混了。
集合是一回事。
被收集的实例之间没有关系。
另外,类级别的变量更新会让我们一些人感到困惑。没错,我们最终能理解发生了什么,但大家通常的期望是,状态的变化应该是针对对象的,而不是类。
class Foobar_Collection( dict ):
def __init__( self, *arg, **kw ):
super( Foobar_Collection, self ).__init__( *arg, **kw ):
def foobar( self, *arg, **kw ):
fb= Foobar( *arg, **kw )
self[fb.name]= fb
return fb
class Foobar( object ):
def __init__( self, name, something )
self.name= name
self.something= something
fc= Foobar_Collection()
fc.foobar( 'first', 42 )
fc.foobar( 'second', 77 )
for name in fc:
print name, fc[name]
这更常见一些。
在你的例子中,wait_for_deps
只是任务集合中的一个方法,而不是单个任务的方法。你不需要全局变量。
你需要重构一下代码。