1

I'm pretty sure I'm heavily abusing Python and I require assistance in fixing it:

I've worked with Java for the past year for school projects and just fiddled around with python a bit in the last few months.

I'm in the middle of a project in python and I really feel like I'm abusing the language and writing as if I'm using Java.

For example: I'm using a specific engine that analyzes some data for me. Since it returns the result in a specific format, I wrote a wrapper object handles the result data (in this case it receives a json and takes the relevant pieces from it).

Since I wanted there to be an abstract Result type for me to work with in the future, I created the following class which is effectively equivalent to a Java abstract class:

class STTResult:

def get_text(self):
    raise NotImplementedError("This is an abstract class")

def get_confidence(self):
    raise NotImplementedError("This is an abstract class")

def get_intent(self):
    raise NotImplementedError("This is an abstract class")

def get_entities(self):
    raise NotImplementedError("This is an abstract class")

and then the concrete class:

class WitResult(STTResult):

def __init__(self,json_result):
    self.text = json_result["_text"]
    self.confidence = json_result["outcomes"][0]["confidence"]
    self.intent = json_result["outcomes"][0]["intent"]
    self.entities = json_result["outcomes"][0]["entities"]


def get_text(self):
    return self.text

def get_confidence(self):
    return self.confidence

def get_intent(self):
    return self.intent

def get_entities(self):
    return self.entities

I'm quite sure this is not pythonic. So how can I get out of the Java, C++, C# mindset and into the python mindset?

Clarification: It's not that I don't know the language / syntax of python. I'm aware of most of the basic features and modules.

5
  • 7
    You do not really need getter/setters when you have simple attributes: obj.intent works just as well as obj.get_intent(). The abstract methods act as documentation (not a terrible idea) but are not otherwise useful.
    – mdurant
    Commented Aug 6, 2014 at 17:29
  • Moreover, the abstract class does nothing for you here. Even if you were to write a second implementation class, you could just as easily have them both inherit from Object instead and there'd be no difference in behavior whatsoever (since they're overriding all the behavior of the parent class anyway). Functions aren't checking argument types, and you should rarely be doing so manually; all that matters is that both classes have the methods -- whether they inherit from a shared superclass is irrelevant. Commented Aug 6, 2014 at 18:04
  • 3
    Also, if you find yourself writing a class with nothing but attributes, getters, and setters, you may as well just use a dictionary. Commented Aug 6, 2014 at 18:06
  • It all depends on how you plan to use the data. So far, you've just made it complicated for no reason. You've already got a dict json_result["outcomes"][0] that is very useful on its own. If you don't need more, don't write more.
    – tdelaney
    Commented Aug 6, 2014 at 18:09
  • 1
    Possibly relevant: Python is not Java
    – Blckknght
    Commented Aug 6, 2014 at 18:28

2 Answers 2

1

Python uses attributes or properties instead of getters and setters. You directly access the variable.

class Point(object):
    def __init__(self):
        super().__init__()

        self.x = 0
        self.y = 0
        self.__my_private_variable = 0 # ".__" for private (Not really private)
    # end Constructor

    def update(self)
        """Do something to update the position on a graph."""
        pass
# end class Point

if __name__ == "__main__":
    p = Point()
    p.x = 1
    p.y = 1
    p.update()

The other way of doing things like getters and setters is to use properties

class Point(object):
    def __init__(self):
        super().__init__()

        self.__x = 0
        self.__y = 0
    # end Constructor

    @property
    def x(self):
        """The x value of a point."""
        return self.__x
    @x.setter
    def x(self, value):
        # Do setter stuff here
        self.__x = value
        self.update()
    # end x

    @property
    def y(self):
        """The y value of a point."""
        return self.__y
    @y.setter
    def y(self, value):
        self.set_y(value)
    # end y property

    def set_y(self, value):
        self.__y = value
        self.update()
    # end set_y

    def update(self):
        # Do something to update the position on a graph.
        pass
    # end update
# end class Point

if __name__ == "__main__":
    p = Point()
    p.x = 1
    p.y = 1
    # "p.x" uses @property method
    # "p.x = 0" uses @x.setter if you don't make an @x.setter then it is read only.
    # "del p.x" uses @x.deleter

This preserves the same syntax style before, so changing the attribute to a property doesn't hurt anything. It also lets you do operations for get, set, and delete.

Also look at the other syntax for using properties (without descriptors). I don't use this approach, so I'm not entirely sure about the syntax.

class Point(object):
    def __init__(self):
        self.__x = 0
        self.x = property(fget=lambda: self.__x, fset=None, fdel=None, doc=None)
0

If your result 'class' does nothing besides contain data, it may as well be a dict. Unless it does have, as Justin Engel has suggested, an 'update' function - but if it follows that whole "this object has two methods and one is __init__()" thing, it probably doesn't need to be a class. It isn't necessarily pythonic to make the container an object just because Python allows for object oriented programming; if you're just getting and setting data, a dict is probably fine.

>>> def make_result(json_data):
>>>     outs = json_data['outcomes'][0]
>>>     return dict(text=json_data['_text'], 
>>>                 confidence=outs['confidence'], 
>>>                 intent=outs['intent'], 
>>>                 entities=outs['entities']
>>>             )
>>> 
>>> MyResult = make_result(your_json_data)
>>> MyResult
{'confidence': 'extremely high', 'entities': ['Rose', 'Martha', 'Donna'], 'intent': 'fun', 'text': 'Allons-y!'}

In the event that it does need to become a new object, keep in mind that getters and setters are only needed if the object is going to have properties. For example, let's assume that an object has three attributes: a, b, and c - and c is always the sum of a and b.

>>> class Thing(object):
>>>     def __init__(self, a, b):
>>>         self.a = a
>>>         self.b = b
>>> 
>>>     @property
>>>     def c(self):
>>>         return self.a + self.b
>>> 
>>> Stick = Thing(4, 5)
>>> Stick.a
4
>>> Stick.b
5
>>> Stick.c
9

This property has no setter, so Stick.c = 34 will result in an error:

Stick.c = 45
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>

However, that may not be a concern at this point and if you're unfamiliar with creating properties in Python you might want to read the official documentation.

There have been more than a few blogs written out of... strong motivation... to point out that Python doesn't work as Java does. MY go-to for this is http://bitworking.org/news/Python_isnt_Java_without_the_compile - take a look at this and get some examples of just how different working with Python can be.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.