【问题标题】:Change attribute after each object calling每个对象调用后更改属性
【发布时间】:2015-03-24 23:18:34
【问题描述】:

我试图弄清楚如何在每次调用对象后更改一些值。 我认为 call() 函数在每次调用后执行。

这应该是一个简单的计数器类,在被调用后会减少 value 属性。

class counter():
    def __init__(self,value):
        self.value = value

    def __call__(self):
        self.value -= 1

count = counter(50)
print count.value
print count.value

>> 50 
>> 50 <-- this should be 49

我做错了什么?

【问题讨论】:

  • __call__ 在您将实例作为函数调用时被调用。即在执行count() 之后,count.value 将是 49。您可能正在寻找 __getattribute__
  • @Matt:我尝试使用 getattribute 但还是一样。你能帮助我吗?谢谢
  • 你想让count.value每次被访问时减1吗?
  • @Matt 是的,我正是想要那个。
  • 它需要是一个类还是你只需要一个计数器?

标签: python class attributes call


【解决方案1】:

如果您不致力于类,则可以使用函数并滥用 mutable-types-as-default-initializers:

def counter(init=None, container=[0]):
    container[0] -= 1
    if init is not None: container[0] = init
    return container[0]


x = counter(100)
print(x) # 100
print( counter() )  # 99
print( counter() )  # 98
print( counter() )  # 97
# ...

使用单个参数调用counter 来设置/初始化计数器。由于初始化实际上是对函数的第一次调用,所以它会返回那个数字。

不带参数调用counter 以获得“下一个值”。

(非常类似于我建议的here

或者,如果语法更接近您的问题,请使用properties

class Counter(object):
    def __init__(self, init):
        self.val = init

    @property
    def value(self):
        val = self.val
        self.val -= 1
        return val

count = Counter(50)

print(count.value)  # 50
print(count.value)  # 49
print(count.value)  # 48
print(count.value)  # 47
#...

在这里,您正在创建一个名为 countCounter 对象,然后每次调用 count.value 时,它都会返回当前值并通过递减其内部 val 属性来为将来的调用做好准备。

同样,当您第一次请求 value 属性时,它会返回您初始化它时使用的数字。

如果出于某种原因,您想“窥视”下一次对 count.value 的调用将是什么,而不减少它,您可以改为查看 count.val

【讨论】:

  • 你应该看看closures。这基本上是您通过使用[] 作为默认参数所做的事情,但是通过使用闭包,您可以使用您的计数器函数来创建多个计数器。看看我的answer
【解决方案2】:

__call__ 仅在您使用() 调用对象时调用

要调用此行为,您必须这样做

class counter():
    def __init__(self,value):
        self.value = value

    def __call__(self):
        print 'called'
        self.value -= 1

count = counter(50)
print count.value
count()
print count.value

这可能不是您想要做的。

【讨论】:

    【解决方案3】:

    Use the property decorator

    class counter:
        def __init__(self, value):
            self._value = value + 1
    
        @property
        def value(self):
            self._value -= 1
            return self._value
    
    count = Counter(50)
    print(count.value)  # 50
    print(count.value)  # 49
    

    或者,您可以使用closure

    def Counter(n):
        n += 1
        def inner():
            n -= 1
            return n
        return inner
    

    虽然每次你想使用它时都必须调用它

    count1 = Counter(50)
    count2 = Counter(50)
    print(count1())  # 50
    print(count1())  # 49
    print(count2())  # 50
    print(count2())  # 49
    print(count1())  # 48
    

    【讨论】:

      【解决方案4】:

      在元类中定义自定义 call() 方法允许在调用类时自定义行为,例如并不总是创建一个新的实例。由于没有创建新的类实例 call 被调用而不是 init。所以这样做以获得所需的结果

      print count.value
      count()
      print count.value
      

      【讨论】:

        猜你喜欢
        • 2013-09-07
        • 1970-01-01
        • 1970-01-01
        • 2019-05-13
        • 2020-10-04
        • 1970-01-01
        • 2013-05-01
        • 1970-01-01
        • 2018-12-31
        相关资源
        最近更新 更多