What's the difference between @property and setting in __init __ ()?

Couldn't get a direct response from other threads on this:

In Python, the main difference between using

class Foo(object):
  def __init__(self, x):
    self.x = x

      

and

class Foo(object):
  def __init__(self, x):
    self._x = x

  @property
  def x(self):
    return self._x

      

Apparently, using @property this way is read-only x .. but maybe someone has a better answer? Thanks / Fred

+3


source to share


3 answers


In your example, yes, it allows you to have read-only attributes. Also, properties can allow you to have more attributes than you actually do. Consider a circle with .radius

and .area

. Area can be calculated based on radius, not storage as



import math

class Circle(object):
    def __init__(self, radius):
        self.radius = radius

    @property
    def area(self):
        return math.pi * (self.radius ** 2)

      

+4


source


The decorator implementation property

uses the descriptor protocol , which is how we encapsulate data in Python OOP. Descriptor:

In general, the handle - an attribute of an object with a binding behavior ", one whose attribute access has been overridden by methods in the descriptor protocol, these methods are. __get__()

, __set__()

And __delete__()

if any of these methods defined for the object, it is called a descriptor..

Typically, other OOP languages ​​use getters and setters. You will often see people show up, like Java, writing a Python class like this:

class A(object):
    def __init__(self, x, y):
        self._x = x
        self._y = y
    def getX(self):
        return self._x
    def getY(self):
        return self._y
    def setX(self, x):
        self._x = x
    def setY(self, y):
        self._y = y
    def some_method_that_uses_attributes(self):
        return self.getX() + self.getY()

      

This is not how you would do anything in Python. The Getters and Setters point should provide data encapsulation. We will encapsulate access to the data attribute by wrapping it in a getter and setter. Then if we ever want to add something, say make sure it's x

never set to a value below 10 (as a contrived example), we just change the way setX

and we don't need to change the rest of our code. However, in Python, we will write the above class like this:



class A(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def some_method_that_uses_attributes(self):
        return self.x + self.y

      

A person who comes from Java may be horrified: "You are not encapsulating your class correctly! This will be a maintenance nightmare!"

No, because we have descriptors / properties:

class A(object):
    def __init__(self, x, y):
        self._x = x
        self.y = y
    @property
    def x(self):
        return self._x
    @x.setter
    def x(self, val):
        if val > 10:
            self._x = val
        else:
            raise ValueError("x must be greater than 10")
    def some_method_that_uses_attributes(self):
        return self.x + self.y

      

And now we don't have to refract every method we use self.x

, for example some_method_that_uses_attributes

. This is good, because it allows us not to write a bunch of boilerplate code, and the implementation of descriptors is relatively straightforward when we need it. Moreover, it makes our code nice and nice, without self.get_this()

and self.set_that(3)

throughout the code, and much more readable self.this

andself.that = 3

+4


source


Please post this SO post on Python properties - this refers to getters / setters, but the answers break down a lot more about them, and I believe everything you want to know is in there: Python @property vs getters and setters

-1


source







All Articles