Управление (и переименование) переменных экземпляра составов классов - PullRequest
0 голосов
/ 10 февраля 2019

Я хотел бы сделать композицию классов так, чтобы переменные экземпляра составляющих классов становились переменными экземпляра композиции, но с измененными именами.

Приложение для этого - определение новых объектов для рисования в matplotlib,Одним из примеров является то, что я хотел бы иметь функцию drawMyArrow, которая рисует стрелку, возможно, разных цветов (и других спецификаций) для ее головы, хвоста и дуги.Я хотел бы иметь возможность передавать различные спецификации для головы, хвоста и дуги через аргументы ключевых слов в drawMyArrow.Раньше я не работал с классами, но, читая об этом в Интернете, я считаю, что лучший способ решить мою проблему - определить класс MyArrow, который представляет собой композицию некоторых классов ArrowHead и ArrowArc.

Чтобы проиллюстрировать мою проблему, рассмотрим простой игрушечный пример.Давайте определим класс Room, который является композицией классов wall, window и door.

class Door:
    def __init__(self, color='white', height=2.3, width=1.0):
        self.color = color
        self.height = height
        self.width = width

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()

Переменные экземпляра Door, Window и Wall являются color, height, width.Я бы хотел, чтобы Room имел переменные экземпляра doorcolor, windowcolor, wallcolor, doorheight, windowheight и т. Д. Я мог бы явно добавить все девять переменных экземпляра в Room и определить set иget функции для них.Но если позже я решу добавить дополнительные переменные экземпляра в Door, Window или Wall, мне всегда нужно будет снова редактировать код для Room.Есть ли способ кодировать Room, чтобы он автоматически принимал (и переименовывал) переменные экземпляра из своих классов компонентов?

1 Ответ

0 голосов
/ 10 февраля 2019

Вы используете композицию - не нужно дублировать средства доступа для ваших участников.Вы можете легко получить доступ к атрибутам через ваших составных членов:

r = Room()
print( r.window.color ) # to print the windows color only

Вы можете получить прибыль от базового класса для ваших "частей" и измененного __init__(..) для вашего Room класс хотя:

class Thing:
    """Base class handling init including a name and __str__ and __repr__."""
    def __init__(self, name, color, height, width):
        self.name = name
        self.color = color
        self.height = height
        self.width = width

    def __str__(self):
        return repr(self)

    def __repr__(self):
        return str([self.name, self.color, self.height, self.width])

class Door(Thing):
    def __init__(self, color='white', height=2.3, width=1.0):
        super(self.__class__, self).__init__(self.__class__.__name__, color, height, width)

class Window(Thing):
    def __init__(self, color='white', height=2.3, width=1.0):
        super(self.__class__, self).__init__(self.__class__.__name__, color, height, width)

class Wall(Thing):
    def __init__(self, color='white', height=2.5, width=4.0):
        super(self.__class__, self).__init__(self.__class__.__name__, color, height, width) 

class Room:
    def __init__(self,*, door=None, window=None, wall=None): # named params only
        self.door = door or Door()           # default to booring Door if none provided
        self.window = window or Window()     # same for Window
        self.wall = wall or Wall()           # same for Wall

    def __str__(self):
        return str([self.door,self.window,self.wall])

Создание объектов и их печать:

r = Room()
r2 = Room(window=Window("yellow"))

print(r)
print(r2)

r3 = Room( window=Window("green",0.5,0.5), door=Door("black",5,5), 
           wall=Wall("unicorncolored",5,5) )

print(r3)

Вывод:

# r - the cheap Room - using default-ing Things
[['Door', 'white', 2.3, 1.0], ['Window', 'white', 2.3, 1.0], ['Wall', 'white', 2.5, 4.0]]

# r2 - with a custom yellow Window
[['Door', 'white', 2.3, 1.0], ['Window', 'yellow', 2.3, 1.0], ['Wall', 'white', 2.5, 4.0]]

# r3 - all custom - 
[['Door', 'black', 5, 5], ['Window', 'green', 0.5, 0.5], ['Wall', 'unicorncolored', 5, 5]]
...