设置类组成对象的属性的功能 [英] Function to set properties of an object of a class composition
问题描述
我想构造一个包含函数set_props
的类组合,该函数用于设置组件的实例变量.
此应用程序是在matplotlib中定义要绘制的新对象.一个例子是我想有一个函数drawMyArrow
,它为箭头的头部,尾部和弧线绘制一个可能具有不同颜色(和其他规格)的箭头.我希望能够通过drawMyArrow
中的关键字参数传递有关头部,尾部和弧线的各种规范.我以前没有使用过类,但是在网上阅读了此书后,我相信解决我的问题的最佳方法是定义一个类MyArrow
,该类由某些类ArrowHead
和ArrowArc
组成./p>
这就是我要做的
class Room:
def __init__(self, kw_door=None, kw_window=None, kw_wall=None):
if kw_door:
self.door = Door(**kw_door)
else:
self.door = Door()
if kw_window:
self.window = Window(**kw_window)
else:
self.window = Window()
if kw_wall:
self.wall = Wall(**kw_wall)
else:
self.wall = Wall()
实际上,您接受的字典将被解包到实例创建中,并且当类定义获得新属性时,如果在传递的字典中找到它们,它们也将被解包.
I would like construct a class composition that includes a function set_props
for setting the instance variables of components.
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, I am using a toy example (that I also used for a previous question here). 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, 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()
If I want to have a function for Room
that can set properties of its components, I can do something like this:
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
But if I decide to add more instance variables to Window
, I would have to go back to this function and add the new instance variables. Can I write set_windowprops
so that it automatically accepts all instance variables of Window
as keywords?
Ideally, I would like to write a function like this:
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
but without the need of hardcoding all instance variables of components into the function.
I was looking into using keyword dictionaries like so:
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
Two issues keep me from getting this to work:
(1) In the last line, I am pretending that r
is a dictionary (of dictionaries) and using dictionary syntax to assign a value to r.window.kw
. But that doesn't work because r
is an instance of Room
and not a dictionary. What would be the syntax for setting instance variables if the name of the component class and the name of the instance variable are given as strings?
(2) I have tried using inspect
to write getNamesOfInstanceVariables
, but I am unable to get it to work robustly. Many classes in matplotlib
inherit from base classes. I would like getNamesOfInstanceVariables
to return all instance variables that a user can set for an object of this class. For example, the class FancyArrow
in matplotlib
has Patch
as base class and instance variables head_length
and head_width
. So I would getNamesOfInstanceVariables(FancyArrow)
to return ['head_length','head_width', *listOfInstanceVarsForPatch]
.
EDIT
Let me add a bit of background on why I am asking for a dynamical way to write these functions. Let's say I have finished my script and it includes the classes Window
, Door
, Wall
and many class compositions of these three. One of these many class compositions is Room
. This class Room
has ten hardcoded set_
functions that look like this:
def set_windowcolor(r, color):
r.window.color = color
return r
I now decide that I want to add another instance variable to the class Window
. For example,
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
Similar to all the other instance variables of window, this new attribute of Window
should be customizable in all classe compositions that contain a Window
. So I would go through my code, find the class Room
and add a function
def set_windowopen(r, open):
r.window.open = open
return r
I would also have to look for all other class compositions that contain a Window
and update them manually as well. I don't want to do this because it is a lot of work and I am likely going to overlook some class dependencies in the process and introduce bugs into my code. I am looking for a solution that either
generates
set
functions for single properties (e.g.set_windowcolor
) automatically inRoom
for all instance variables ofWindow
orautomatically adjusts the list of keyword arguments in
set_windowprops
orset_props
.
Here is what I would do
class Room:
def __init__(self, kw_door=None, kw_window=None, kw_wall=None):
if kw_door:
self.door = Door(**kw_door)
else:
self.door = Door()
if kw_window:
self.window = Window(**kw_window)
else:
self.window = Window()
if kw_wall:
self.wall = Wall(**kw_wall)
else:
self.wall = Wall()
effectively you are accepting a dictionary that will be unpacked into the instance creation, and when the class definition gets new attributes, they too will be unpacked if they are found in the passed dictionary.
这篇关于设置类组成对象的属性的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!