2

I am trying to modify an attribute that is defined in a class. For this problem, I had to modify the names of the attributes to include private_ in the beginning. So, if it was previously self.a, it is now self.private_a in self.__dict__. However, it should still work with the methods defined in the class. I have this bump method that increments some of the attributes, and when getattr is implemented, the updated values are added to a new key instead.

For example, if my self.dict is

{'private_a': 1, 'private_b': 2, 'c': 3, 'd': 5} 

and I call bump, I get this

{'private_a': 1, 'private_b': 2, 'c': 4, 'd': 5, 'a': 2, 'b': 3}

What I want is:

{'private_a': 2, 'private_b': 3, 'c': 4, 'd': 5 }

What am i doing wrong?

def bump(self):
    self.a += 1
    self.b += 1
    self.c += 1

def __getattr__(self,name):
    calling = inspect.stack()[1]

    if calling.function in C.__dict__:
        actual = 'private_' + name
        if actual in self.__dict__:
            return self.__dict__[actual]


    if name not in self.__dict__:
        raise NameError
hannahtran
  • 21
  • 4
  • 1
    suggest you implement `__setattr__` and make sure that `private_` is always prepended to the attribute's name.`__getattr__` isn't used for setting attributes. – Geotob Apr 27 '17 at 02:30
  • I should clarify that I already have a __setattr__ method. The point of the assignment and for this particular question is to be able to use __getattr__ to be able to add to modify attributes that don't have private_ in their name – hannahtran Apr 27 '17 at 02:48
  • When you say `self.a += 1`, Python will *essentially* (not literally) do something like `self.__setattr__('a', self.__getattr__('a') + 1)`. I'm not sure how you could modify `__getattr__` for modifying attributes, or why anyone would want you to do that.. – Geotob Apr 27 '17 at 02:56

1 Answers1

1

You mean this ?

class A(object):

    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def __getattribute__(self, item):
        if not item.startswith('__'):
            return object.__getattribute__(self, 'private_' + item)
        return object.__getattribute__(self, item)

    def __getitem__(self, item):
        return object.__getattribute__(self, 'private_' + item)

    def __setitem__(self, key, value):
        object.__setattr__(self, 'private_' + key, value)

    def __setattr__(self, key, value):
        object.__setattr__(self, 'private_' + key, value)

The result is:

> a = A(a=1, b=2, c=3)
> a.__dict__
{'private_a': 1, 'private_c': 3, 'private_b': 2}
>a['a']
1

>a['d']= 1
>a.__dict__
{'private_d': 1, 'private_a': 1, 'private_c': 3, 'private_b': 2}
>a['d'] += 1
>a.__dict__
{'private_d': 2, 'private_a': 1, 'private_c': 3, 'private_b': 2}

>a.f = 1
>a.__dict__
{'private_d': 2, 'private_f': 1, 'private_a': 1, 'private_c': 3, 'private_b': 2}
gushitong
  • 1,898
  • 16
  • 24