在init中重新分配self

时间:2015-07-14 06:24:07

标签: python

我有一个类在类体中有查找字典,我存储所有实例和一些键。

当我实例化实例时,我没有在任何变量或外部字典中保存它们,我将它们存储在这个查找字典中。

当我以某种方式实例化已经存在于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)

2 个答案:

答案 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_initializedxy等。但如果您这样做,你可以把它关掉。

答案 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