I want some of my class methods to be not re-assignable outside (or both outside and inside) of the class. A's functions are objects too in python, is it possible to accomplish what I want? Here is the method;
def x(self):
"""Return x, the horizontal distance between the shape and the leftmost
of the screen, in pixels.
"""
return self.__x
Now outside of the class, it is easy to mess with this method;
shape = Shape(10, 20)
shape.x = 30
print(shape.x) # Prints 30
print(shape.x()) # TypeError: 'int' object is not callable
Is it possible to prevent this kind of assignment of class methods?
CodePudding user response:
You could override the __setattr__ method to check to see if the key is in a forbidden list for example...
class Shape:
def __init__(self, a, b):
self.__x = a
self.__y = b
def x(self):
return self.__x
def __setattr__(self, key, value):
if key in ('x', 'y'):
raise TypeError(f"You can't change {key}")
super(Shape, self).__setattr__(key, value)
shape = Shape(11, 20)
shape.z = 100 # OK
print(shape.z)
print(shape.x())
shape.x = 30 # raise an exception
note: As @Chepner noted, Overriding __setattr__ just prevents you from changing the value of x via an assignment statement, not from changing it at all. like object.__setattr__(shape, 'x', 30)
CodePudding user response:
Make x a property with no setter, not a method.
class Shape:
...
@property
def x(self):
return self.__x
Attempts to assign to x will result in an exception:
>>> shape.x = 30
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
If you really want something that must be called, have the property return that instead of the value the function will return.
class Shape:
@property
def x(self):
return lambda: self.__x
