Your options fall into two substantial categories: you either copy the attributes from _CarType
into Car
, or set Car
's metaclass to a custom one with a __getattr__
method that delegates to _CarType
(so it isn't exactly true that you can't use __getattr__
: you can, you just need to put in in Car
's *meta*class rather than in Car
itself;-).
The second choice has implications that you might find peculiar (unless they are specifically desired): the attributes don't show up on dir(Car)
, and they can't be accessed on an instance of Car
, only on Car
itself. 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'
You could fix the "not from an instance" issue by also adding a __getattr__
to Car
:
>>> class Car:
... __metaclass__ = MetaGetattr
... types = _CarType
... def __getattr__(self, nm):
... return getattr(self.types, nm)
...
to make both kinds of lookup work, as is probably expected:
>>> Car.GAS_CAR_ENGINE
1
>>> Car().GAS_CAR_ENGINE
1
However, defining two, essentially-equal __getattr__
s, doesn't seem elegant.
So I suspect that the simpler approach, "copy all attributes", is preferable. In Python 2.6 or better, this is an obvious candidate for a class decorator:
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
In general, it's worth defining a decorator if you're using it more than once; if you only need to perform this task for one class ever, then expanding the code inline instead (after the class
statement) may be better.
If you're stuck with Python 2.5 (or even 2.4), you can still define typesfrom
the same way, you just apply it in a slightly less elegant matter, i.e., the Car
definition becomes:
class Car(object):
pass
Car = typesfrom(_CarType)(Car)
Do remember decorator syntax (introduced in 2.2 for functions, in 2.6 for classes) is just a handy way to wrap these important and frequently recurring semantics.