仅实例化 class 的唯一 objects
Instantiate only unique objects of a class
我正在尝试创建一个 class,它仅在实例化期间传入的参数是唯一组合时才创建一个实例。如果先前已传入参数组合,则 return 先前已创建的实例。
我希望此 class 被其他 class 继承,以便它们继承相同的行为。这是我第一次尝试解决方案,
要继承的base/parentclass:
class RegistryType(type):
def __init__(cls, name, bases, namespace, *args):
cls.instantiated_objects = {}
class AdwordsObject(object, metaclass=RegistryType):
api = AdWordsAPI()
def __new__(cls, *args):
object_name = '-'.join(args)
if object_name in cls.instantiated_objects:
return cls.instantiated_objects[object_name]
else:
obj = super(AdwordsObject, cls).__new__(cls)
cls.instantiated_objects[object_name] = obj
# cls.newt_connection.commit()
return obj
这就是它在 child class 中的使用方式:
class ProductAdGroup(AdwordsObject):
# init method only called if object being instantiated hasn't already been instantiated
def __init__(self, product_name, keyword_group):
self.name = '-'.join([product_name, keyword_group])
@classmethod
def from_string(cls, name: str):
arguments = name.split('-')
assert len(arguments) == 2, 'Incorrect ad group name convention. ' \
'Use: Product-KeywordGroup'
ad_group = cls(*arguments)
return ad_group
我已经 运行 使用此设置的程序,但似乎每次创建 ProductAdGroup() 时都会创建一个新的字典,因此内存正在爆炸......即使程序 returns 之前已经实例化的实例。
有办法解决这个问题吗?
谢谢!!!
你的代码似乎是正确的 - 上面唯一不正确的地方是你的 __init__
方法在实例化一个新的 class 时总是被调用,而不管 __new__
与否。
因此,如果您在 __init__
方法中创建了额外的对象,这可能是内存泄漏的原因 - 但是,如果您将这些新对象绑定到实例 (self),它们应该只是覆盖先前在同一位置创建的对象 - 它们将被释放。 .在此处发布的代码中,self.name
会发生这种情况 - 可能是您真正的 __init__
做了更多的事情,并将新对象关联到实例以外的其他地方(例如,将它们附加到列表中)。如果您的 __init__
方法与所示的一样,那么您提供的代码中内存增长的原因并不明显。
作为额外的建议,但与您所涉及的问题无关,我补充说您根本不需要元class。
只需检查 __new__
方法本身是否存在 cls.instantiated_objects
字典。不编写不需要的 metaclass 将简化您的代码库,如果您的 class 层次结构发生变化,则可以避免 metaclass 冲突,如果您的 meta[ 上有更多代码,甚至可以消除您的问题=32=] 比你在这里展示的要多。
基础class __new__
方法可以改写成这样:
class AdwordsObject(object):
def __new__(cls, *args):
if not cls.__dict__.get("instantiated_objects"):
cls.instantiated_objects = {}
name = '-'.join(args)
if name in cls.instantiated_objects:
return cls.instantiated_objects[name]
instance = super().__new__(cls)
cls.instantiated_objects[name] = instance
return instance
并且不再需要自定义元数据class。
我正在尝试创建一个 class,它仅在实例化期间传入的参数是唯一组合时才创建一个实例。如果先前已传入参数组合,则 return 先前已创建的实例。 我希望此 class 被其他 class 继承,以便它们继承相同的行为。这是我第一次尝试解决方案,
要继承的base/parentclass:
class RegistryType(type):
def __init__(cls, name, bases, namespace, *args):
cls.instantiated_objects = {}
class AdwordsObject(object, metaclass=RegistryType):
api = AdWordsAPI()
def __new__(cls, *args):
object_name = '-'.join(args)
if object_name in cls.instantiated_objects:
return cls.instantiated_objects[object_name]
else:
obj = super(AdwordsObject, cls).__new__(cls)
cls.instantiated_objects[object_name] = obj
# cls.newt_connection.commit()
return obj
这就是它在 child class 中的使用方式:
class ProductAdGroup(AdwordsObject):
# init method only called if object being instantiated hasn't already been instantiated
def __init__(self, product_name, keyword_group):
self.name = '-'.join([product_name, keyword_group])
@classmethod
def from_string(cls, name: str):
arguments = name.split('-')
assert len(arguments) == 2, 'Incorrect ad group name convention. ' \
'Use: Product-KeywordGroup'
ad_group = cls(*arguments)
return ad_group
我已经 运行 使用此设置的程序,但似乎每次创建 ProductAdGroup() 时都会创建一个新的字典,因此内存正在爆炸......即使程序 returns 之前已经实例化的实例。
有办法解决这个问题吗? 谢谢!!!
你的代码似乎是正确的 - 上面唯一不正确的地方是你的 __init__
方法在实例化一个新的 class 时总是被调用,而不管 __new__
与否。
因此,如果您在 __init__
方法中创建了额外的对象,这可能是内存泄漏的原因 - 但是,如果您将这些新对象绑定到实例 (self),它们应该只是覆盖先前在同一位置创建的对象 - 它们将被释放。 .在此处发布的代码中,self.name
会发生这种情况 - 可能是您真正的 __init__
做了更多的事情,并将新对象关联到实例以外的其他地方(例如,将它们附加到列表中)。如果您的 __init__
方法与所示的一样,那么您提供的代码中内存增长的原因并不明显。
作为额外的建议,但与您所涉及的问题无关,我补充说您根本不需要元class。
只需检查 __new__
方法本身是否存在 cls.instantiated_objects
字典。不编写不需要的 metaclass 将简化您的代码库,如果您的 class 层次结构发生变化,则可以避免 metaclass 冲突,如果您的 meta[ 上有更多代码,甚至可以消除您的问题=32=] 比你在这里展示的要多。
基础class __new__
方法可以改写成这样:
class AdwordsObject(object):
def __new__(cls, *args):
if not cls.__dict__.get("instantiated_objects"):
cls.instantiated_objects = {}
name = '-'.join(args)
if name in cls.instantiated_objects:
return cls.instantiated_objects[name]
instance = super().__new__(cls)
cls.instantiated_objects[name] = instance
return instance
并且不再需要自定义元数据class。