1

Let's say I have a class A

class A:
    __slots__ = ['_x']

    def __init__(self):
         self._x = 10
    
    @property
    def x(self):
        return self._x

And I want to restrcit assigning to a._x from anywhere except other instance's methods.

How do I do that? Is that even possible in Python?

The thing is to write a class which attributes is changeable only within particular methods and never directly from outside.

1

2 Answers 2

2

Python doesn't really have "private" variables like C++. Even if you set the variable as private by using a the _ prefix from PEP8 (as you have done). You can always access the variable using A._x.

If you want to emulate private variables for some reason, you can use __ (double underscore) prefix as it mangles the name. Similarly you can use @property decorator to make a getter and setter function and prevent access to the attribute. However, even these fail as you can access the variables directly using __dict__.

So the Pythonic way is to leave it the way it is. Python is like perl in this respect. To paraphrase a famous line about privacy from the Perl book,

the philosophy is that you should stay out of the living room because you weren't invited, not because it is defended with a shotgun.

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

1 Comment

Well, I'm not completely new to Python and am familiar with this philosophy. In this particular case, however, I was looking for a workaround. Kinda thing you want to do just because. As an exercise :) But I guess it would be already implemented if it were possible. Thanks for stopping me from wasting time :)
-1

I totally agree with @kinshukdua on this. However, just to explore more options available to you. you can override the setattr by placing some condition

This might not be the most pythonic way, but i am open to a more cleaner way to acheive this.

class A:
    _x = 10 #dont think you need an init method since you are not adding any data
    def __setattr__(self, key, value):
        if 'yes' in value[1]:
            super().__setattr__(key,value[0])
        else:
            raise TypeError('You should not have access to this')

    def change(self, value,loc= 'yes'):
        self._x = value,loc
        return self._x
        
    
    

1 Comment

I actually thought of metaprogramming to solve this. Like creating a metaclass which creates Lock object and context manager for it and attaches it to a class instance and then overrides the setattr magic method so after that attributes can be added and assigned only if Lock is opened. Do all of that during 'new' call and then use a lock to assign other attributes during init or other methods calls.

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.