当使用用户元类创建 类 时如何将项目添加到 __slots__
How to add items to __slots__ when the classes are created with user metaclass
背景
我想制作一个工具来创建 对象 ,这些对象 没有相同的 属性 。最后我决定创建一个 UniqueInstances metaclass
class UniqueInstances(type):
def __new__(cls, name, bases, dict):
dict['instancesAttrs'] = set()
return super(UniqueInstaces, cls).__new__(cls, name, bases, dict)
def __call__(cls, *args):
if args not in cls.instancesAttrs:
cls.instancesAttrs.add(args)
return super().__call__(*args)
else:
print("Warning: " +
"There is another instance of the class " +
"'{}' ".format(cls.__name__) +
"with the same attributes. The object was not created.")
return None
有了这个 metaclass
我可以创建 类 避免创建具有相同属性的对象
class Coordinate(metaclass=UniqueInstances):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
myObj = Coordinate(0, 0, 0)
myObj = Coordinate(0, 0, 0) # Warning: There is another instance...
及其作品。
问题
我希望使用此工具创建的 类 有一个 __slots__
来优化实例。我可以用空元组
添加到 dict
__slot__
键
class UniqueInstances(type):
def __new__(cls, name, bases, dict):
dict['instancesAttrs'] = set()
dict['__slots__'] = ()
return super(UniqueInstaces, cls).__new__(cls, name, bases, dict)
及其作品
class MyClass(metaclass=UniqueInstances):
pass
myObj = MyClass()
print(myObj.__dict__) # AttributeError: 'MyClass' object has no attribute '__dict__'
但是,我不知道如何向 __slots__
添加项目
class Coordinate(metaclass=UniqueInstances):
__slots__ = ('x', 'y', 'z')
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
myObj = Coordinate(0, 0, 0) # AttributeError: 'Coordinate' object has no attribute 'x'
有什么想法吗?
有点难看,但是你可以在 class 定义语法中将关键字参数传递给 metaclass,比如:
class Coordinate(metaclass=UniqueInstances, slots=('x', 'y', 'z')):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
元class可以按如下方式处理:
class UniqueInstances(type):
def __new__(cls, name, bases, dict, **kwargs):
dict['instancesAttrs'] = set()
slots = kwargs.get('slots')
if slots is not None:
dict['__slots__'] = slots
return super(UniqueInstances, cls).__new__(cls, name, bases, dict)
编辑:
实际上,我刚刚检查过,只使用 __slots__
就可以了,你可以在 metaclass 中删除 dict['__slots__'] = ()
,所以只是:
class UniqueInstances(type):
def __new__(cls, name, bases, dict, **kwargs):
dict['instancesAttrs'] = set()
return super(UniqueInstances, cls).__new__(cls, name, bases, dict)
class Coordinate(metaclass=UniqueInstances):
__slots__ = ('x','y','z')
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
有效。它会创建您期望的开槽 class。
背景
我想制作一个工具来创建 对象 ,这些对象 没有相同的 属性 。最后我决定创建一个 UniqueInstances metaclass
class UniqueInstances(type):
def __new__(cls, name, bases, dict):
dict['instancesAttrs'] = set()
return super(UniqueInstaces, cls).__new__(cls, name, bases, dict)
def __call__(cls, *args):
if args not in cls.instancesAttrs:
cls.instancesAttrs.add(args)
return super().__call__(*args)
else:
print("Warning: " +
"There is another instance of the class " +
"'{}' ".format(cls.__name__) +
"with the same attributes. The object was not created.")
return None
有了这个 metaclass
我可以创建 类 避免创建具有相同属性的对象
class Coordinate(metaclass=UniqueInstances):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
myObj = Coordinate(0, 0, 0)
myObj = Coordinate(0, 0, 0) # Warning: There is another instance...
及其作品。
问题
我希望使用此工具创建的 类 有一个 __slots__
来优化实例。我可以用空元组
dict
__slot__
键
class UniqueInstances(type):
def __new__(cls, name, bases, dict):
dict['instancesAttrs'] = set()
dict['__slots__'] = ()
return super(UniqueInstaces, cls).__new__(cls, name, bases, dict)
及其作品
class MyClass(metaclass=UniqueInstances):
pass
myObj = MyClass()
print(myObj.__dict__) # AttributeError: 'MyClass' object has no attribute '__dict__'
但是,我不知道如何向 __slots__
class Coordinate(metaclass=UniqueInstances):
__slots__ = ('x', 'y', 'z')
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
myObj = Coordinate(0, 0, 0) # AttributeError: 'Coordinate' object has no attribute 'x'
有什么想法吗?
有点难看,但是你可以在 class 定义语法中将关键字参数传递给 metaclass,比如:
class Coordinate(metaclass=UniqueInstances, slots=('x', 'y', 'z')):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
元class可以按如下方式处理:
class UniqueInstances(type):
def __new__(cls, name, bases, dict, **kwargs):
dict['instancesAttrs'] = set()
slots = kwargs.get('slots')
if slots is not None:
dict['__slots__'] = slots
return super(UniqueInstances, cls).__new__(cls, name, bases, dict)
编辑:
实际上,我刚刚检查过,只使用 __slots__
就可以了,你可以在 metaclass 中删除 dict['__slots__'] = ()
,所以只是:
class UniqueInstances(type):
def __new__(cls, name, bases, dict, **kwargs):
dict['instancesAttrs'] = set()
return super(UniqueInstances, cls).__new__(cls, name, bases, dict)
class Coordinate(metaclass=UniqueInstances):
__slots__ = ('x','y','z')
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
有效。它会创建您期望的开槽 class。