Ваши параметры делятся на две существенные категории: вы либо копируете атрибуты из _CarType
в Car
, либо устанавливаете метакласс Car
в пользовательский с помощью метода __getattr__
, который делегирует _CarType
( так что это не совсем верно, что вы не можете использовать __getattr__
: вы можете, вам просто нужно вставить в Car
' meta класс, а не в Car
сам ;-) .
Второй вариант имеет последствия, которые могут показаться вам странными (если только они не требуются специально): атрибуты не отображаются на dir(Car)
, и , к ним нельзя получить доступ на экземпляр из Car
, только на самом Car
. I.e.:
>>> class MetaGetattr(type):
... def __getattr__(cls, nm):
... return getattr(cls.types, nm)
...
>>> class Car:
... __metaclass__ = MetaGetattr
... types = _CarType
...
>>> Car.GAS_CAR_ENGINE
1
>>> Car().GAS_CAR_ENGINE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'GAS_CAR_ENGINE'
Вы можете исправить проблему «не из экземпляра», добавив также , добавив __getattr__
к Car
:
>>> class Car:
... __metaclass__ = MetaGetattr
... types = _CarType
... def __getattr__(self, nm):
... return getattr(self.types, nm)
...
чтобы оба вида поиска работали, как это, вероятно, и ожидается:
>>> Car.GAS_CAR_ENGINE
1
>>> Car().GAS_CAR_ENGINE
1
Однако определение двух , по существу равных __getattr__
с, не выглядит элегантным.
Так что я подозреваю, что более простой подход, "копировать все атрибуты", предпочтительнее. В Python 2.6 или выше, это очевидный кандидат на декоратор класса:
def typesfrom(typesclass):
def decorate(cls):
cls.types = typesclass
for n in dir(typesclass):
if n[0] == '_': continue
v = getattr(typesclass, n)
setattr(cls, n, v)
return cls
return decorate
@typesfrom(_CarType)
class Car(object):
pass
В общем случае стоит определить декоратор, если вы используете его более одного раза; если вам нужно выполнить эту задачу только для одного класса, то лучше вместо этого расширить встроенный код (после оператора class
).
Если вы застряли с Python 2.5 (или даже 2.4), вы все равно можете определить typesfrom
таким же образом, просто примените его в чуть менее элегантном вопросе, то есть определение Car
становится:
class Car(object):
pass
Car = typesfrom(_CarType)(Car)
Помните, синтаксис декоратора (введенный в 2.2 для функций, в 2.6 для классов) - это просто удобный способ обернуть эту важную и часто повторяющуюся семантику.