我想构造一个具有特殊行为的对象,我很确定它可以用python(使用生成器或某种棘手的类定义)来完成。
我基本上想要一个对象让我们调用它 - colourgun
,每次访问它时都会从预定义颜色列表中返回颜色。所以它应该像一个简单的变量,但每次访问它时都要改变它的行为。
您可以在以下示例中看到一个类似的概念:
class CounterList(list):
def __init__(self, *args):
super(CounterList, self).__init__(*args)
self.counter = 0
def __getitem__(self, index):
self.counter += 1
return super(CounterList, self).__getitem__(index)
CounterList
的实例每次访问列表时都会增加counter
,因为__getitem__
被调用。
我的colourgun
应该能够检测到它何时被“使用”并且表现得像这样:
>>> gun = Colourgun() # or a function, a generator, whatever...
>>> print gun
'predefined_colour1'
>>> print gun
'predefined_colour2'
>>> print gun
'predefined_colour3'
>>> print gun # no more colours left: reloading and maybe warn the user
[WARNING] automatically reloading the gun
'predefined_colour1'
>>> gun.load(['colour1', 'colour2', 'colour3']) # some way to load it with colours
>>> print gun
'colour1'
>>> print gun
'colour2'
>>> gun.reload() # manually reloading
>>> print gun
'colour1'
关键是,我不想在每次访问变量时显式调用“拍摄颜色”的方法。我想这是一个信号,表明该变量确实应该是一个函数或一个生成器(它至少可以冻结它的状态)。
我尝试了一下,这是一个尝试更接近这个想法,但它不起作用,因为我绑定了Shoot()的返回值而不是函数本身与变量gun
:
class ColourGun(object) :
def __init__(self) :
self.colours = ['predefined_colour1', 'predefined_colour2', 'predefined_colour3']
self.counter = 0
def Shoot(self) :
c = self.colours[self.counter]
self.counter += 1
return c
gun = ColorGun().Shoot()
print gun
print gun
print gun
当然打印出predefined_colour1
三次......
所以肯定有一个基于生成器或类和生成器或其他东西的组合的概念,它可以用pythonic方式来实现。 (或者可能是设计模式?)
P.S。:如果您对更好的标题有所了解并随时添加更多标签,请告诉我......
更新
所以使用属性(如wim建议的那样):
class ColorGun(object) :
def __init__(self) :
self.colours = ['predefined_colour1', 'predefined_colour2', 'predefined_colour3']
self.counter = 0
@property
def Shoot(self) :
if self.counter >= len(self.colours) :
self.counter = 0
print "automatically reloading"
c = self.colours[self.counter]
self.counter += 1
return c
gun = ColorGun()
print gun.Shoot
print gun.Shoot
print gun.Shoot
print gun.Shoot
给出了输出:
predefined_colour1
predefined_colour2
predefined_colour3
automatically reloading
predefined_colour1
实现reload
方法没有问题,但是我可以以某种方式摆脱.
,所以我可以将其称为gun
而不是gun.Shoot
吗? ; - )
答案 0 :(得分:5)
这样的东西......?
import itertools as it
class ColourGun(object):
def __init__(self):
self._colourgen = it.cycle(['predefined_colour1', 'predefined_colour2', 'predefined_colour3'])
def load(self, colours):
self._colourgen = it.cycle(colours)
@property
def colour(self):
return next(self._colourgen)
def __str__(self):
return self.colour
gun = ColourGun()
print gun
print gun
print gun
gun.load(['potato', 'spam', 'eggs'])
print gun
print gun
答案 1 :(得分:2)
由于您的being used
表示print gun
,我们只需自定义__str__
方法。
class ColorGun:
def __init__(self):
self.colors = ['red', 'pink']
self.i = 0
def __str__(self):
if not self.colors:
return
if self.i >= len(self.colors):
print '[WARNING] automatically reloading the gun.'
self.reload()
c = self.colors[self.i]
self.i += 1
return c
def reload(self, colors=None):
if colors:
self.colors = colors
self.i = 0
gun = ColorGun()
print gun
print gun
print gun
答案 2 :(得分:1)
您可能希望自定义__str__
功能以实现此目的。这是一个简单的例子。
此示例显示mylist
的项目(您可以使用生成器),当它耗尽时,会打印一个默认值。
class Gun():
mylist=[1,2,3]
index=-1
default='Default'
def __str__(self):
try:
self.index+=1
return str(self.mylist[self.index])
except IndexError:
return self.default
>>> gun=Gun()
>>> print gun
1
>>> print gun
2
>>> print gun
3
>>> print gun
Default
>>>