В Python 3.6 появилась новая функция для решения этой модели, и dimini sh требует метаклассов, поскольку они почти всегда приводят к путанице.
Все, что нужно, - это чтобы классы объектов, которые должны быть атрибутами, имели метод __set_name__
(в вашем случае это все подклассы Musician
, поэтому все, что вам нужно сделать, это чтобы добавить def __set_name__(self, owner, name): ...
метод к нему).
Итак, все, что вам нужно в вашем случае:
class Musician:
def __init__(self, ...):
# no need to get a 'name' parameter here
...
# This is called automatically by Python:
def __set_name__(self, owner, name):
# 'owner' is the class object where the attributes are defined in.
# in this case, "Beatles". It is usually not needed, but available.
self.name = name
class Guitar(Musician):
pass
class Bass(Musician):
pass
class Drums(Musician):
pass
class Beatles(metaclass=Meta):
john = Guitar()
paul = Bass()
george = Guitar()
ringo = Drums()
Теперь, если по какой-то причине вы хотите реализовать это с помощью метаклассы (допустим, вы должны работать с Python 3.5 или не можете изменить код для классов Musician
) - вы можете использовать functools.partial для хранения других атрибутов и просто передать отсутствующий атрибут name
в тот же код метакласса, который у вас есть выше:
from functools import partial
class Beatles:
john = partial(Guitar, other_attribute='')
paul = partial(Bass, wearing_shoes=False)
george = partial(Guitar)
ringo = partial()
(И имейте в виду, что при желании вы можете сократить partial
для удобства чтения, с такими простыми вещами, как from functools import partial as P
)