如何创建可以给类提供实例数组并提供"voodoo"信息的元类.对所有类实例起作用的实例? [英] How to create a metaclass that can give a class an array of instances and provide a "voodoo" instance that acts on all class instances?
问题描述
我想知道如何在Python中创建一个可以创建其他类的元类:
I'm wondering how to create a metaclass in Python that can create other classes that:
- 自动将其实例存储在数组中
- 具有一个特殊实例
NonMetaClass.all
,其属性为:- 设置后,请使用相同的键将所有类的实例设置为相同的值(例如,
Foo.all.num = 3
会使Foo
的所有实例的num
均为3) - 在访问(获取)时,返回该类实例的所有键值的数组(例如,
Foo.all.num
返回[5, 3, 2]
) - 无法删除.
- 在调用(如果属性是函数)时,请在类的所有实例上调用该方法.
- Store their instances in an array automatically
- Have a special instance,
NonMetaClass.all
, whose properties:- When set, set all the class's instances with the same key to the same value (e.g.,
Foo.all.num = 3
makes all instances ofFoo
have anum
of 3) - When accessed (get), returns an array of all of the class's instances's key values (e.g.,
Foo.all.num
returns[5, 3, 2]
) - Cannot be deleted.
- When called (if the attribute is a function), call that method on all the instances of a class.
用Python来讲,我想打开一个像这样的类:
In Python terms, I would like to turn a class that is like this:
class Foo(object): BAR = 23 def __init__(self): self.a = 5 def pointless(): print 'pointless.' def change_a(self): self.a = 52
对此:
class Foo(object): BAR = 23 instances = [] all = # Some black magic to create the special "all" instance def __init__(self): self.a = 5 Foo.instances.append(self) def pointless(self): print 'pointless.' def change_a(self): self.a = 52
并能够像这样使用它:
>>> Foo() >>> Foo.instances[0] <__main__.Foo instance at 0x102ff5758> >>> Foo() >>> len(Foo.instances) 2 >>> Foo.all.a = 78 78 >>> Foo.all.a [78, 78] >>> Foo.all.change_a() >>> Foo.all.a [52, 52] >>>
推荐答案
好吧,我想出了如何针对Python 2.7单独执行此操作.我认为这可能是最好的解决方案,尽管它可能不是唯一的解决方案.它允许您设置,获取和函数调用
Class.all
的属性.我已经将元类命名为InstanceUnifier
,但是如果您认为可以想到一个更好的名称(简短,更具描述性),请发表评论.Ok, I figured out how to do this for Python 2.7 on my own. This is what I believe to be the best solution though it may not be the only one. It allows you to set, get, and function call on attributes of
Class.all
. I've named the metaclassInstanceUnifier
, but please comment if you think there's a better (shorter, more descriptive) name you can think of.class InstanceUnifier(type): ''' What we want: A metaclass that can give a class an array of instances and provide a static Class.all object, that, when a method is called on it, calls the same method on every instance of the class. ''' def __new__(cls, name, base_classes, dct): dct['all'] = None dct['instances'] = [] return type.__new__(cls, name, base_classes, dct) def __init__(cls, name, base_classes, dct): class Accessor(object): def __getattribute__(self, name): array = [getattr(inst, name) for inst in cls.instances] if all([callable(item) for item in array]): def proxy_func(*args, **kwargs): for i in range(len(cls.instances)): this = cls.instances[i] func = array[i] func(*args, **kwargs) return proxy_func elif all([not callable(item) for item in array]): return array else: raise RuntimeError('Some objects in class instance array for key "'+name+'" are callable, some are not.') def __setattr__(self, name, value): [setattr(inst, name, value) for inst in cls.instances] def __delattr__(self, name): [delattr(inst, name) for inst in cls.instances] cls.all = Accessor() return type.__init__(cls, name, base_classes, dct) def __call__(cls, *args, **kwargs): inst = type.__call__(cls, *args, **kwargs) cls.instances.append(inst) return inst
这篇关于如何创建可以给类提供实例数组并提供"voodoo"信息的元类.对所有类实例起作用的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- When set, set all the class's instances with the same key to the same value (e.g.,
- 设置后,请使用相同的键将所有类的实例设置为相同的值(例如,