Одна очень важная вещь, о которой следует знать - если эти атрибуты останутся в классе, поколение __slots__
будет бесполезным ... хорошо, может быть, не бесполезно - это сделает класс атрибуты только для чтения; вероятно, не то, что вы хотите.
Самый простой способ - сказать: «Хорошо, я инициализирую их как None, а затем позволю им исчезнуть». Отлично! Вот один из способов сделать это:
class B(object):
three = None
four = None
temp = vars() # get the local namespace as a dict()
__slots__ = temp.keys() # put their names into __slots__
__slots__.remove('temp') # remove non-__slots__ names
__slots__.remove('__module__') # now remove the names from the local
for name in __slots__: # namespace so we don't get read-only
del temp[name] # class attributes
del temp # and get rid of temp
Если вы хотите сохранить эти начальные значения, потребуется немного больше работы ... вот одно из возможных решений:
class B(object):
three = 3
four = 4
def __init__(self):
for key, value in self.__init__.defaults.items():
setattr(self, key, value)
temp = vars()
__slots__ = temp.keys()
__slots__.remove('temp')
__slots__.remove('__module__')
__slots__.remove('__init__')
__init__.defaults = dict()
for name in __slots__:
__init__.defaults[name] = temp[name]
del temp[name]
del temp
Как видите, это можно сделать без метакласса - но кому нужен весь этот шаблон? Метакласс может определенно помочь нам очистить это:
class MakeSlots(type):
def __new__(cls, name, bases, attrs):
new_attrs = {}
new_attrs['__slots__'] = slots = attrs.keys()
slots.remove('__module__')
slots.remove('__metaclass__')
new_attrs['__weakref__'] = None
new_attrs['__init__'] = init = new_init
init.defaults = dict()
for name in slots:
init.defaults[name] = attrs[name]
return super(MakeSlots, cls).__new__(cls, name, bases, new_attrs)
def new_init(self):
for key, value in self.__init__.defaults.items():
setattr(self, key, value)
class A(object):
__metaclass__ = MakeSlots
one = 1
two = 2
class B(object):
__metaclass__ = MakeSlots
three = 3
four = 4
Теперь все утомительные вещи хранятся в метаклассе, а реальный класс легко читать и (надеюсь!) Понимать.
Если вам нужно иметь что-то еще в этих классах, кроме атрибутов, я настоятельно рекомендую вам поместить все, что есть, в класс mixin - наличие их непосредственно в конечном классе еще больше усложнит метакласс.