简体   繁体   English

检测Python循环中的值更改

[英]Dectecting a value change in Python loop

Here is a pattern I often use: 这是我经常使用的模式:

last_value = None

while <some_condition>:
    <get current_value from somewhere>
    if last_value != current_value:
       <do something>

    last_value = current_value

One application example would be to print headings in a report when, say, a person's last name changes. 一个应用示例是,例如,当一个人的姓名发生变化时,在报告中打印标题。

The whole last_value/current_value thing has always seemed clumsy to me. 整个last_value / current_value对我来说总是显得笨拙。 Is there a better way to code this in Python? 有没有更好的方法在Python中编写代码?

I agree that your pattern makes a lot of sense. 我同意你的模式很有意义。

But for fun, you could do something like: 但为了好玩,你可以这样做:

class ValueCache(object):
    def __init__(self, val=None):
        self.val = val

    def update(self, new):
        if self.val == new:
            return False
        else:
            self.val = new
            return True

Then your loop would look like: 然后你的循环看起来像:

val = ValueCache()
while <some_condition>:    
    if val.update(<get current_value from somewhere>):
        <do something>

For example 例如

import time
t = ValueCache()
while True:
    if t.update(time.time()):
        print("Cache Updated!")

If you changed time.time() to some static object like "Foo", you'd see that "Cache Updated!" 如果你将time.time()更改为某个静态对象,如“Foo”,你会看到“Cache Updated!” would only appear once (when it is initially set from None to "Foo"). 只出现一次(当它最初从None设置为“Foo”时)。

Obligatory realistic programmer's note: Don't do this. 强制性的现实程序员注意:不要这样做。 I can't easily find a good reason to do this in practice. 我不能轻易找到在实践中这样做的好理由。 It not only adds to the line count but to the complexity. 它不仅增加了行数,还增加了复杂性。

(Inspired by Alex Martelli's Assign and Test Recipe ) (灵感来自Alex Martelli的 分配和测试配方

I think the pattern is very clear, but you can use a generator function to hide the last_value/current_value thing. 我认为模式非常清晰,但您可以使用生成器函数来隐藏last_value / current_value事物。

def value_change_iterator(iterable):
    last_x = None
    for x in iterable:
        if x != last_x:
            yield x
        last_x = x

for x in value_change_iterator([1, 1, 2, 2, 3, 3, 4]):
    print(x)

prints 版画

1
2
3
4

Another alternative inspired by @jedwards' answer inspired by Alex Martelli's recipe (this one keeps around the current and last values, and lets you use None as an initial value if you're so inclined, also changes the semantics from semantics I don't particularly like to other semantics I'm not sure I much like either): 另一个受@jedwards答案启发的另一个选择是受到Alex Martelli的配方的启发(这一个保留了当前和最后的值,并允许你使用None作为初始值,如果你如此倾向,也改变了语义我没有的语义特别喜欢其他语义,我不确定我是否也喜欢):

class undefined:
    pass

class ValueCache:
    def __init__(self, value=undefined):
        self.current_value = value
        self.last_value = undefined
        self._is_changed = False

    @property
    def is_changed(self):
        is_changed = self._is_changed
        self._is_changed = False
        return is_changed

    def update(self, new_value):
        self._is_changed = (new_value != self.current_value)
        if self._is_changed:
            self.last_value = self.current_value
            self.current_value = new_value

Example: 例:

>>> v = ValueCache()
>>> v.update(1)
>>> v.is_changed
True
>>> v.is_changed is False
False
>>> v.update(2)
>>> v.is_changed
True
>>> v.is_changed
False

Or in your case: 或者在你的情况下:

t = ValueCache()
while True:
    t.update(time.time())
    if t.is_changed:
        print("Cache updated!")

Same obligatory realistic programmer's note applies. 同样的强制性现实程序员注意适用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM