Gianni Spear
Gianni Spear

Reputation: 7934

Resolving how to give an attribute in a class in Python

I have the following class:

class Point(object):
    __slots__= ("x","y","z","data","classification")
    def __init__(self,x,y,z,n=None):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.data = [self.x,self.y,self.z]

    def set_classification(self,n):
        self.classification = n

p = Point(10,20,30)
p.data
[10.0, 20.0, 30.0]
p.set_classification(0)
p.data
[10.0, 20.0, 30.0]

I have the following questions:

First, the parameters to create the Point object are x,y, and z. Classification is an accessory parameter (some time is report inside the file other no). I wish to find a way, if it's possible, to have p.data = [10.0, 20.0, 30.0, 50.0] when classification is set or p.data = [10.0, 20.0, 30.0] when classification is not set.

By the way, I use set_classification

def set_classification(self,n):
      self.classification = n

Upvotes: 2

Views: 121

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121914

You could use a property to handle classification instead:

class Point(object):
    __slots__= ("x", "y", "z", "data", "_classification")
    def __init__(self, x, y, z):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.data = [self.x,self.y,self.z]

    @property
    def classification(self):
        return getattr(self, '_classification', None)

    @classification.setter
    def classification(self, value):
        self._classification = value
        if value:
            self.data = self.data[:3] + [value]
        else:
            self.data = self.data[:3]

This sets up a getter and a setter for a classification attribute; accessing the classification attribute translates into the first method being called. Setting the classification attribute translates in the setter, the second method, being called instead:

p = Point(1, 2, 3)
p.classification = 50  # calls the second `classification` method, the setter, for you.
print p.classification # calls the first `classification` method, the getter.

I picked the classification attribute as the property here, but you could make data a property instead as well. Which one you make into a property depends on usage patterns and intent. If classification is rarely changed, making it the property would be more efficient.

Upvotes: 2

Fabian
Fabian

Reputation: 4348

Getter and setter methods are generally frowned upon. You can use a property to achieve this, however I'd recommened to always include classification in your return value, just because other parts of your script might expect that data is always a 4-item list. APIs should be consistent.

Here's my take on it using a property:

class Point(object):
    __slots__= ("x", "y", "z", "data", "classification")
    def __init__(self, x, y, z, n=None):  ## what's n for?
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)

        self.classification = None

    @property
    def data(self):
        if self.classification:
            return [self.x, self.y, self.z, self.classification]
        else:
            return [self.x, self.y, self.z]

p = Point(10, 20, 30)
print p.data   ## [10.0, 20.0, 30.0]
p.classification = 50.0
print p.data   ## [10.0, 20.0, 30.0, 50.0]

Upvotes: 2

Related Questions