Managing (and renaming) instance variables of clas

2019-07-10 01:48发布

I would like to make a class composition so that the instance variables of the composing classes become instance variables of the composition but with adjusted names.

The application for this is in defining new objects for drawing in matplotlib. One example is that I would like to have a function drawMyArrow that draws an arrow with possibly different colors (and other specifications) for its head, tail, and arc. I would like to be able to pass various specifications for the head, tail, and arc via keyword arguments in drawMyArrow. I haven't worked with classes before, but reading up on this online, I believe that the best way to solve my problem is to define a class MyArrow that is a composition of some classes ArrowHead and ArrowArc.

To illustrate my problem, consider a simple toy example. Let's define a class Room that is a composition of the classes wall, window, and 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()

The instance variables of Door, Window, and Wall are color, height, width. I would like Room to have instance variables doorcolor, windowcolor, wallcolor, doorheight, windowheight, etc. I could add all nine instance variables to Room explicitly and define set and get functions for them. But if I later decide to add more instance variables to Door, Window, or Wall I would always need to edit the code for Room again too. Is there a way to code Room so that it adopts (and renames) the instance variables from its component classes automatically?

1条回答
可以哭但决不认输i
2楼-- · 2019-07-10 02:47

You are using composition - no need to replicate accessors for your members. You can easily access the attributes through your composed members:

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

You might profit from a base class for your "parts" and a changed __init__(..) for your Room class though:

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

Create objects and print them:

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)

Output:

# 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]]
查看更多
登录 后发表回答