我有一个类在类体中有查找字典,我存储所有实例和一些键。
当我实例化实例时,我没有在任何变量或外部字典中保存它们,我将它们存储在这个查找字典中。
当我以某种方式实例化已经存在于dict中的实例时,我将其重新分配给dict中的实例并更新它,在其他函数中使用它的新旧值。
我想知道这是不是一个好习惯?或者我应该重构并让它有一个外部字典来保存实例。
是否有针对此类行为的PEP指南?
示例:
class MyClass:
all_instances = {} # this dictionary is in local space and it's clear that
# the only interaction is with MyClass
def __init__(self, unique_id, x, y, z):
if unique_id not in MyClass.all_instances:
self.unique_id = unique_id
self.x = x
self.y = y
self.z = z
MyClass.all_instances[unique_id] = self
else:
self = MyClass.all_instances[unique_id]
self.update(x, y, z)
def update(self, new_x, new_y, new_z):
self.x = self.do_something_with(self.x, new_x)
self.y = self.do_something_with(self.y, new_y)
self.z = self.do_something_with(self.z, new_z)
@staticmethod
def do_something_with(old_value, new_value):
# do something with old value and new and return some value
value = (old_value + new_value) / 2 # more complicated than tht
return value
while True:
for id in get_ids(): # fetch ids from some database
x, y, z = get_values(id) # fetch values from some other database
MyClass(id, x, y, z)
我得到id和值的数据库每次都在变化,所以我无法确定我是否会得到我已经实例化的数据,或者值会有所不同。
我看到的方式是,类的所有功能都在其自身内部发生,不需要使用字典,因此不清楚它们与代码的任何其他部分的交互位置。
这就是我通常会做的事情,如果没有重新分配它:
class MyClass:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def update(self, new_x, new_y, new_z):
self.x = self.do_something_with(self.x, new_x)
self.y = self.do_something_with(self.y, new_y)
self.z = self.do_something_with(self.z, new_z)
@staticmethod
def do_something_with(old_value, new_value):
# do something with old value and new and return some value
value = (old_value + new_value) / 2 # more complicated than tht
return value
all_instances = {} # this dictionary is now in global space
# and it's unclear if the only interaction is with MyClass
while True:
for id in get_ids(): # fetch ids from some database
x, y, z = get_values(id) # fetch values from some other database
if id not in all_instances:
all_instances[id] = MyClass(x, y, z)
else:
all_instances[id].update(x, y, z)
答案 0 :(得分:4)
你在这里得到的是一个类似单身的模式。 (我说像单身一样,因为你实际上并没有一个实例,而是一组实例键入了几个参数)。有lots of reason why singletons (and global data in general) are a bad idea,所以我投票给外部注册表。
但是,如果稍微考虑一下,如果您确定做想要使用“内部”注册表,则可以使用__new__
来执行此操作。
class MyClass(object):
all_instances = {}
def __new__(cls, unique_id, x, y, z):
instance = cls.all_instances.get(unique_id)
if instance is not None:
instance.is_initialized = True
else:
instance = super(MyClass, cls).__new__(cls, unique_id, x, y, z)
instance.is_initialized = False
return instance
def __init__(self, unique_id, x, y, z):
if self.is_initialized:
return
# Do initialization here.
注意__new__
如何用于更改对象创建的方式。如果我们已经有一个注册对象,我们返回它而不是创建一个新对象 - 否则,我们在超类(__new__
)上调用object
,它给我们一个新的(未初始化的)实例{ {1}}。调用MyClass
后(假设它返回__new__
的实例),将调用MyClass
。这可能会导致同一对象多次调用__init__
(这就是所有__init__
业务所涉及的内容。
is_initialized
位是可选的 - 我假设您不想重置is_initialized
,x
,y
等。但如果您这样做,你可以把它关掉。
答案 1 :(得分:1)
result = {}
class abc:
def __init__(self) : pass
def update(self,_id,old,new):
result["res:"+str(_id)] = (old + new)/2.0
def clean(self,command):
for e in result.keys():
if e.startswith("res:"):
if command == "to_zero": result[e]= 0
elif command == "del": del result[e]
def read(self,_id):
if "res:"+_id in result.keys() : return _id,result["res:"+_id]
result["fun"] = abc()
result['fun'].update("hello",8,3)
print result["fun"].read("hello")
>>>
('hello', 5.5)
>>>
请给我很多 - 浪费用户的时间。也许Si tacuisses, philosophus mansisses