gpt4 book ai didi

python - 在 init 中重新分配 self

转载 作者:太空狗 更新时间:2023-10-30 02:43:59 24 4
gpt4 key购买 nike

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

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

当我以某种方式实例化一个已经在字典中的实例时,我将它重新分配给字典中的实例并更新它,在其他函数中使用它的新值和旧值。

我想知道这是否是一个好的做法?或者我应该重构并使其具有一个包含实例的外部字典。

是否有针对此类行为的 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)

最佳答案

你在这里得到的是一个类似单例的模式。 (我说像单例一样,因为您实际上并没有只有一个实例,而是一组实例关闭了几个参数)。有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__ 是如何用来改变对象创建的方式的。如果我们已经有一个已注册的对象,我们返回它而不是创建一个新对象——否则,我们调用父类(super class)(object)上的__new__,这给了我们一个新的MyClass 的(未初始化的)实例。在 __new__ 被调用后(假设它返回一个 MyClass 的实例),__init__ 将被调用。这可能导致 __init__ 被同一对象多次调用(这就是所有 is_initialized 业务的意义所在。

is_initialized 位是可选的——我假设您不想重置 xyz 等。但如果您这样做,则可以将其关闭。

关于python - 在 init 中重新分配 self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31399170/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com