构造一个对象,每次访问它时都会改变其状态,并且行为类似于变量

tam*_*gal 3 python properties

我想构造一个具有特殊行为的对象,我很确定它可以用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)
Run Code Online (Sandbox Code Playgroud)

每次访问列表时都会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'
Run Code Online (Sandbox Code Playgroud)

关键是,我不希望每次访问变量时都明确地调用"拍摄颜色"的方法.我想这是一个标志,变量确实应该是一个函数或一个生成器(它至少可以冻结它的状态).

我尝试了一点,这是一个尝试更接近这个想法,但它不起作用,因为我绑定了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
Run Code Online (Sandbox Code Playgroud)

当然打印出predefined_colour1三次......

所以肯定有一个基于生成器或类和生成器或其他东西的组合的概念,它可以用pythonic方式来实现.(或者可能是设计模式?)

PS:如果您对更好的标题有所了解并随时添加更多标签,请告诉我......

UPDATE

所以使用属性(如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
Run Code Online (Sandbox Code Playgroud)

这给出了输出:

predefined_colour1
predefined_colour2
predefined_colour3
automatically reloading
predefined_colour1
Run Code Online (Sandbox Code Playgroud)

实现一个reload方法没有问题,但我可以以某种方式摆脱它.,所以我可以称之为gun而不是gun.Shoot?;-)

wim*_*wim 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
Run Code Online (Sandbox Code Playgroud)

  • 在需要对属性获取,设置或删除有兴趣的地方时,属性非常有用.一个常见的用法示例是限制属性,以便只能将其设置为受控的输入组. (2认同)