0

Consider the following Python class. I want to set the attr property of class A internally, which method is the preferred way? I do not want to implement the property setter method because the user of the class should not be allowed to alter the attribute.

class A:
    ''' Library code '''
    def __init__(self):
        self._attr = None

    @property
    def attr(self):
        return self._attr

    # first approach
    def _set_attr(self, data):
        # Set the underlying private attribute
        self._attr = data

    # second approach
    def _set_attr2(self, data):
        # This calls __setattr__() of the base class
        setattr(self, '_attr', data)

    # third approach
    def _set_attr3(self, data):
        # Assignes data directly to the instance attribute
        self.__dict__['_attr'] = data

   def sets_attr(self):
        ''' does calculations and only calls the setter when
            result is fulfilling some requirements. '''


class B(A):
    ''' User code - extend on library code
        User can set any attribute name except the protected name  'attr'
    '''


5
  • The first approach is clearly the more sensible of these three options; there is no need to use setattr or __dict__ with a fixed attribute name. But you should use the @attr.setter decorator with it. Commented Feb 11, 2020 at 9:47
  • Does this answer your question? How to set attributes using property decorators? Commented Feb 11, 2020 at 9:49
  • "I do not want to implement the property setter method because the user of the class should not be allowed to alter the attribute." Then why are you writing a setter method in the first place? The purpose of a setter method is to allow the user to alter the attribute. Commented Feb 11, 2020 at 9:52
  • I just made the question more clear considering the suggested setter method. Commented Feb 11, 2020 at 9:52
  • You might want to use two underscores, not just one Commented Feb 11, 2020 at 10:03

1 Answer 1

4

I wouldn't use any approach. Your use case is not clear, but if you do not want a setter available, and setting this attribute will only be done from some other internal module/class you are providing with no special action on set, there is not much point in any wrapper here. Just use

my_object._attr = value # Or if only within the class itself, then self._attr = value

wherever you intended to call the setter. A setter is an API for setting - if you do not want to provide an interface for setting, don't.

Sign up to request clarification or add additional context in comments.

3 Comments

Presumably because this code is only used inside the class, it would always be self._attr (unless you specifically want to set the attribute on a different instance). But this hits the nail on the head.
And if you ever need to intercept all these cases, you can use a property with def _attr() I don't think there is anything wrong with having an accessor as part of the private api that isn't exposed.
@juanpa.arrivillaga I agree, there is no "wrong" here. Just preferences. Since Python does not have a real concept of "private" (beyond name conventions) this is what I prefer assuming nothing special needs to be done on setting and the setting itself is only meant to be done by the original developer. Wrappers seem extraneous to me in this case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.