lima
lima

Reputation: 361

Python: how to count the access of an instance variable

I have a python class as below.

class A(object):
   def __init__(self, logger):
       self.b = B()
       self.logger = logger
   def meth1(self):
       self.b.mymethod1()
   def meth2(self):
       self.meth1()
       self.b.mymethod2()
   .........
class B(object):
   ---------

How can I count how many time I accessed self.b variable on the invocation of meth2() or any method of class A. Is there any way, I can log the usage of self.b variable?

Upvotes: 4

Views: 345

Answers (4)

Jean-François Fabre
Jean-François Fabre

Reputation: 140168

If you don't want to make a property, you can log the read/write access using __getattribute__ (not __getattr__ since b exists and would not be called) and __setattr__:

class A(object):
   def __init__(self):
       # initialize counters first !
       self.b_read_counter = 0
       self.b_write_counter = 0
       # initialize b
       self.b = 12

   def __getattribute__(self,attrib):
      # log read usage
      if attrib=="b":
          self.b_read_counter+=1
      # now return b value
      return object.__getattribute__(self, attrib)

   def __setattr__(self,attrib,value):
      if attrib=="b":
          self.b_write_counter+=1

      return object.__setattr__(self, attrib,value)

a = A()

a.b = 23    # second write access (first is in the init method)
if a.b == 34:  # first read access
    print("OK")
if a.b == 34:
    print("OK")
if a.b == 34:  # third read access
    print("OK")
print(a.b_read_counter)
print(a.b_write_counter)

result:

3
2

Upvotes: 3

Aviad
Aviad

Reputation: 349

You can use property, somtehing like:

class A(object):
  def __init__(self, logger):
      self._b = B()
      self._count = 0
      self.logger = logger

  @property
  def b(self):
     self._count += 1
     return self._b
  ...
  ...

Upvotes: 0

armak
armak

Reputation: 560

make 'b' a property and and increase the counter corresponding to be in the setter.

@property
def b(self):
  self.b_counter += 1
  return self._b

and in your class replace b with _b

Upvotes: 3

Sardorbek Imomaliev
Sardorbek Imomaliev

Reputation: 15370

You can use descriptors for this or just make a property which is basically is descriptor.

class A(object):
   def __init__(self, logger):
       self._b = B()
       self._b_counter = 0
       self.logger = logger

   @property
   def b(self):
       self._b_counter += 1
       return self._b

   def meth1(self):
       self.b.mymethod1()

   def meth2(self):
       self.meth1()
       self.b.mymethod2()

Upvotes: 1

Related Questions