Я хотел бы создать композицию класса, которая включает функцию set_props
для установки переменных экземпляра компонентов.Приложение для этого в определении новых объектов для рисования в matplotlib.Одним из примеров является то, что я хотел бы иметь функцию drawMyArrow
, которая рисует стрелку, возможно, разных цветов (и других спецификаций) для ее головы, хвоста и дуги.Я хотел бы иметь возможность передавать различные спецификации для головы, хвоста и дуги через аргументы ключевых слов в drawMyArrow
.Раньше я не работал с классами, но, читая об этом в Интернете, я считаю, что лучший способ решить мою проблему - определить класс MyArrow
, который представляет собой композицию некоторых классов ArrowHead
и ArrowArc
.
Чтобы проиллюстрировать мою проблему, я использую игрушечный пример (который я также использовал для предыдущего вопроса здесь ).Давайте определим класс Room
, который является композицией классов wall
, window
и door
.
class Door:
def __init__(self, color='white', height=2.3, width=1.0, locked=True):
self.color = color
self.height = height
self.width = width
self.locked=locked
class Window:
def __init__(self, color='white', height=1.0, width=0.8):
self.color = color
self.height = height
self.width = width
class Wall:
def __init__(self, color='white', height=2.5, width=4.0):
self.color = color
self.height = height
self.width = width
class Room:
def __init__(self):
self.door = Door()
self.window = Window()
self.wall = Wall()
Если я хочу иметь функцию для Room
, которая может устанавливатьсвойства его компонентов, я могу сделать что-то вроде этого:
def set_windowprops(r, color=None, width=None, height=None):
if not color==None: r.window.color=color
if not width==None: r.window.widht=width
if not height==None: r.window.height=height
return r
Но если я решу добавить дополнительные переменные экземпляра в Window
, мне придется вернуться к этой функции и добавить новые переменные экземпляра,Могу ли я написать set_windowprops
, чтобы он автоматически принимал все переменные экземпляра Window
в качестве ключевых слов?
В идеале я хотел бы написать такую функцию:
def set_props(r, windowcolor=None, windowwidth=None, windowheight=None,
doorcolor=None, doorwidth=None, doorheight=None, doorlocked=None,
wallcolor=None, wallwidth=None, wallheight=None):
if not windowcolor==None: r.window.color=windowcolor
if not windowwidth==None: r.window.widht=windowwidth
if not windowheight==None: r.window.height=windowheight
if not doorcolor==None: r.door.color=doorcolor
if not doorwidth==None: r.door.widht=doorwidth
if not doorheight==None: r.door.height=dooorheight
if not doorlocked==None: r.door.locked=doorlocked
if not wallcolor==None: r.wall.color=wallcolor
if not wallwidth==None: r.wall.widht=wallwidth
if not wallheight==None: r.wall.height=wallheight
return r
, но безнеобходимость жесткого кодирования всех переменных экземпляра компонентов в функцию.
Я искал словари ключевых слов, например, так:
window_vars = getNamesOfInstanceVariables(Window) #TODO
window_kwargs = {}
for v in window_vars:
window_kwargs[v] = None
def set_windowprops(r, **kwargs):
for kw in kwargs:
if not kwargs[kw]==None:
r["window"][kw] = kwargs[kw] #TODO
return r
Две проблемы не позволяют мне заставить это работать:
(1) В последней строке я притворяюсь, что r
является словарем (словарей), и использую синтаксис словаря для присвоения значения r.window.kw
.Но это не работает, потому что r
является экземпляром Room
, а не словарем.Какой будет синтаксис для установки переменных экземпляра, если имя класса компонента и имя переменной экземпляра заданы в виде строк?
(2) Я пытался использовать inspect
для записи getNamesOfInstanceVariables
,но я не могу заставить его работать надежно.Многие классы в matplotlib
наследуются от базовых классов.Я бы хотел, чтобы getNamesOfInstanceVariables
вернул все переменные экземпляра, которые пользователь может установить для объекта этого класса.Например, класс FancyArrow
в matplotlib
имеет Patch
в качестве базового класса и переменных экземпляра head_length
и head_width
.Поэтому я бы getNamesOfInstanceVariables(FancyArrow)
вернул ['head_length','head_width', *listOfInstanceVarsForPatch]
.
РЕДАКТИРОВАТЬ
Позвольте мне добавить немного фона, почему я прошу динамический способ написания этихфункции.Допустим, я закончил свой сценарий, и он включает в себя классы Window
, Door
, Wall
и множество композиций классов этих трех.Одна из этих классных композиций - Room
.Этот класс Room
имеет десять жестко закодированных set_
функций, которые выглядят следующим образом:
def set_windowcolor(r, color):
r.window.color = color
return r
Теперь я решаю, что хочу добавить еще одну переменную экземпляра в класс Window
.Например,
class Window:
def __init__(self, color='white', height=1.0, width=0.8, open=False):
self.color = color
self.height = height
self.width = width
self.open = open # new attribute of Window
Подобно всем другим переменным экземпляра окна, этот новый атрибут Window
должен быть настраиваемым во всех классовых композициях, которые содержат Window
.Так что я бы просмотрел свой код, нашел класс Room
и добавил бы функцию
def set_windowopen(r, open):
r.window.open = open
return r
. Мне также пришлось бы искать все другие композиции классов, содержащие Window
, и обновлять их вручную.,Я не хочу этого делать, потому что это большая работа, и я, вероятно, собираюсь пропустить некоторые классовые зависимости в процессе и внести ошибки в мой код.Я ищу решение, которое либо
генерирует set
функций для отдельных свойств (например, set_windowcolor
) автоматически в Room
для всех переменных экземпляра Window
или
автоматически корректирует список аргументов ключевых слов в set_windowprops
или set_props
.