JS.*_*JS. 2 python oop design-patterns
假设我有一个班级:
class Car(object):
def __init__(self, name, tank_size=10, mpg=30):
self.name = name
self.tank_size = tank_size
self.mpg = mpg
Run Code Online (Sandbox Code Playgroud)
我把我正在看的车列表放在一起:
cars = []
cars.append(Car("Toyota", 11, 29))
cars.append(Car("Ford", 15, 12))
cars.append(Car("Honda", 12, 25))
Run Code Online (Sandbox Code Playgroud)
如果我为当前收藏夹指定了一个名称(如果你愿意的话,将一个"指针"放入列表中):
my_current_fav = cars[1]
Run Code Online (Sandbox Code Playgroud)
我可以轻松访问我当前最喜欢的属性:
my_current_fav.name # Returns "Ford"
my_current_fav.tank_size # Returns 15
my_current_fav.mpg # Returns 12
Run Code Online (Sandbox Code Playgroud)
这是我开始变得模糊的地方.我想仅为我当前的收藏提供额外的"计算"属性(让我们假设这些属性太"昂贵",无法存储在原始列表中,并且更容易计算):
my_current_fav.range # Would return tank_size * mpg = 180
# (if pointing to "Ford")
Run Code Online (Sandbox Code Playgroud)
在我的情况下,我只是投降并添加'范围'作为Car()的属性.但是如果在每个Car()实例中存储'range'是昂贵但计算它很便宜怎么办?
我考虑让'my_current_fav'成为Car()的子类,但是我无法找到一种方法来做到这一点,并且仍然能够将'my_current_favorite'简单地"指向"'汽车'列表中的条目.
我还考虑使用装饰器来计算和返回'范围',但是无法找到一种方法来提供对属性'name','mpg'等的访问.
是否有一种优雅的方式指向列表'cars'中的任何项目,提供对所指向实例的属性的访问,以及提供Car类中没有的其他属性?
附加信息:
在阅读了许多答案之后,我看到我应该在原始问题中加入背景信息.我不会单独评论很多答案,而是在这里添加其他信息.
这个问题是对更复杂问题的简化.最初的问题涉及对现有库的修改.虽然使方法调用而不是属性是一个很好的方法,但改变
some_var = my_current_favorite.range
Run Code Online (Sandbox Code Playgroud)
至
some_var = my_current_favorite.range()
Run Code Online (Sandbox Code Playgroud)
在许多现有的用户脚本中会很昂贵.哎呀,追踪这些用户脚本将是昂贵的.
同样,我目前对每辆车的计算范围的方法在Python方面并不"昂贵",但在运行时是昂贵的,因为真实世界的模拟需要对(嵌入式)OS的慢速调用.虽然Python本身并不慢,但这些调用是,所以我正在寻求最小化它们.
对于您的示例而言,这是最容易做到的,无需更改Car,并尽可能少地更改,使用__getattr__:
class Car(object):
def __init__(self, name, tank_size=10, mpg=30):
self.name = name
self.tank_size = tank_size
self.mpg = mpg
class Favorite(object):
def __init__(self, car):
self.car = car
def __getattr__(self, attr):
return getattr(self.car, attr)
@property
def range(self):
return self.mpg * self.tank_size
cars = []
cars.append(Car("Toyota", 11, 29))
cars.append(Car("Ford", 15, 12))
cars.append(Car("Honda", 12, 25))
my_current_fav = Favorite(cars[1])
print my_current_fav.range
Run Code Online (Sandbox Code Playgroud)
在实例上找不到的任何属性都Favorite将在Favorite实例car属性上查找,该属性是在您创建时设置的Favorite.
你的例子range对于要添加的东西来说并不是特别好的例子Favorite,因为它应该只是一个property汽车,但我简单地使用它.
编辑:请注意,此方法的一个好处是,如果您更改自己喜欢的汽车,并且您没有存储任何汽车特定的汽车Favorite,您可以将现有的收藏夹更改为另一辆汽车:
my_current_fav.car = cars[0] # or Car('whatever')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |