Python Forum
Preserve Encapsulation while Displaying Information
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Preserve Encapsulation while Displaying Information
#1
Suppose I've got the following class to represent a Car and Tire

class Tire:

    def __init__(self, id, name, type):
        self.id = id
        self.name = name
        self.type = type

    @property
    def getID(self):
        return self.id
    
    @property
    def getName(self):
        return self.name

    @property
    def getType(self):
        return self.Type

    def __str__(self):
        return "ID: {0} Name: {1} Type: {2}".format(self.id, self.name, self.type)
class Car:

    def __init__(self, ID, name, tire, engine):
        self.ID = ID
        self.name = name
        self.tire = tire
        self.engine = engine

    @property
    def getID(self):
        return self.ID

    @property
    def getName(self):
        return self.name

    @property
    def getTire(self):
        return self.tire

    @property
    def getEngine(self):
        return self.engine

    def __str__(self):
        return "ID: {0} Name:{1} Tire: {2} Engine: {3}".format(self.ID, self.name, self.tire, self.engine)
Suppose I want to follow OOP principals, given that Tire is an attribute of a Car, how would I return the details of my Tire object?

If I had GUI with fields for each Car attribute, so calling the __str__ is not applicable, I would need to use my getters, would providing a getter for Tire be appropriate or should I expose the tire attributes in Car? or to put it in code:

This:

class Car:

    def __init__(self, ID, name, tire, engine):
        self.ID = ID
        self.name = name
        self.tire = tire
        self.engine = engine

    @property
    def getID(self):
        return self.ID

    @property
    def getName(self):
        return self.name

    @property
    def getTire(self):
        return self.tire

    @property
    def getEngine(self):
        return self.engine
    
    @property
    def getTire(self):
        return self.tire

    def __str__(self):
        return "ID: {0} Name:{1} Tire: {2} Engine: {3}".format(self.ID, self.name, self.tire, self.engine)
Or:

class Car:

    def __init__(self, ID, name, tire, engine):
        self.ID = ID
        self.name = name
        self.tire = tire
        self.engine = engine

    @property
    def getID(self):
        return self.ID

    @property
    def getName(self):
        return self.name

    @property
    def getTire(self):
        return self.tire

    @property
    def getEngine(self):
        return self.engine

    @property
    def getTireID(self):
        return self.tire.getID
    
    @property
    def getTireName(self):
        return self.tire.getName
    
    @property
    def getTireType(self):
        return self.tire.getType

    def __str__(self):
        return "ID: {0} Name:{1} Tire: {2} Engine: {3}".format(self.ID, self.name, self.tire, self.engine)
In the real world, I can open the hood of my car and see all the details I want, the engine, the tires, etc.. I can even get the ID, and Google it if I wanted too. So the second approach seems approiate, but if I update my Tire class with an attribute that the customer/buyer should know about then that means I need to update car as well. I like the first option, but I'm unsure. What is the appropriate(OOP) way to handle this?
Reply
#2
This is not Java.  As far as python goes, we don't code this way.  Unless a getter/setter actually does work, you don't write one.

So your car should just be:
class Car:
    def __init__(self, ID, name, tire, engine):
        self.ID = ID
        self.name = name
        self.tire = tire
        self.engine = engine
 
    def __str__(self):
        template = "ID: {ID} Name: {name} Tire: {tire} Engine: {engine}"
        return template.format(**vars(self))
If someone wants to access an attribute of tire they just do so using mycar.tire.name for example.
Python has a "we are all consenting adults" philosophy on data  access.  There are no private/public attributes so not only is writing getters/setters not recommended; it is actually pointless.  I can access all those attributes if I want to.

Basically, Python doesn't enforce encapsulation (and if you are trying to enforce it you are writing bad python).  You still use encapsulation by coding responsibly.
Reply
#3
QueenSvetlana Wrote:I would need to use my getters, would providing a getter for
As mention over Python Is Not Java
Quote:Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans.
Do not write getters and setters.
This is what the 'property' built-in is for. And do not take that to mean that you should write getters and setters, and then wrap them in 'property'.
That means that until you prove that you need anything more than a simple attribute access,
don't write getters and setters.
They are a waste of CPU time, but more important, they are a waste of programmer time.
Not just for the people writing the code and tests, but for the people who have to read and understand them as well.

Car should usually be first and Tire a subclass.
Example:
class Car:
    def __init__(self, id, name, type):
        self.id = id
        self.name = name
        self.type = type

    def __str__(self):
        return "ID: {0} Name: {1} Type: {2} Tire: {3} Engine: {4} ".\
           format(self.id, self.name, self.type, self.tire, self.engine)

class Tire(Car):
    def __init__(self, id, name, type, tire, engine):
        super().__init__(id, name, type)
        self.tire = tire
        self.engine = engine
Use:
Output:
>>> car = Tire(100, 'Opel', 'Astra', 'Goodyear', 1.9) >>> car.type 'Astra' >>> car.id 100 >>> car.tire 'Goodyear' >>> print(car) ID: 100 Name: Opel Type: Astra Tire: Goodyear Engine: 1.9
Reply
#4
The article is good.  Tire being a subclass of Car is insane though.  Maybe a language issue.
Reply
#5
python does have private class variables
class MyClass:
    def __init__(self, value):
        self.__value = value

a = MyClass(1)
try:
    print(a.__value)
except:
    print("Sorry variable is private")
99 percent of computer problems exists between chair and keyboard.
Reply
#6
(Dec-07-2017, 03:55 AM)Windspar Wrote: python does have private class variables
That variable is absolutely not private.  It is what is called "name mangled" and can still be accessed with effort.  It is also highly discouraged in python.
class Car:
    def __init__(self, name):
        self.__name = name


mycar = Car("Stratus")
print(mycar._Car__name)
Output:
Stratus
https://docs.python.org/3/tutorial/class...-variables
Reply
#7
@QueenSvetlana
1. You break python style.
def get_id
2. Not a proper name for variables. getID or get_id are methods names. But you are always free to do what you want.
99 percent of computer problems exists between chair and keyboard.
Reply
#8
(Dec-07-2017, 03:41 AM)Mekire Wrote: Tire being a subclass of Car is insane though.  Maybe a language issue.
Yes was not the best example,engine and tire could be sub-classes of car if there where detailed l information about these parts.
But as you show is the more normal way for basic information. 
(Dec-07-2017, 03:55 AM)Windspar Wrote: python does have private class variables
Double underscore(__) is used for name mangling,and are not private.
Reply
#9
I think @Mekire provided the answer I was looking for. Which brings me to another question, if getter/setters shouldn't be used, how do I indicate to someone using my code that they should treat a variable as "cannot be set after construction, but you can get it"? or In other words, it's initialized when you create the object, but can't be changed afterward(so no setters), but you can get the value that you gave in the constructor.

I don't think Tire should be a subclass of Car. Inheritance indicates a "is-a" relationship. A Tire is not Car, an Engine is not a Car, but they're components of a Car. A Car has an Engine, A Car has a set of Tires.
Reply
#10
@Mekire @snippsat
docs says 1 underscore for non public variables. section 9.6
So it is python way of support private class variables.
99 percent of computer problems exists between chair and keyboard.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python Encapsulation codinglearner 2 1,458 Apr-02-2024, 01:26 PM
Last Post: DataScience
  python-docx: preserve formatting when printing lines Tmagpy 4 2,104 Jul-09-2022, 01:15 AM
Last Post: Tmagpy
  tabula-py, how to preserve a read_pdf() format and export to csv abcoelho 2 3,315 Mar-24-2021, 08:34 PM
Last Post: abcoelho
  Function encapsulation Oldman45 4 2,305 Jan-22-2021, 11:38 AM
Last Post: Oldman45
  How to preserve x-axis labels despite deleted subplot? Mark17 1 1,938 Dec-23-2020, 09:02 PM
Last Post: Mark17
  Preserve xml file format tanffn 3 3,894 Jan-03-2020, 09:35 AM
Last Post: Larz60+
  Pygal: Displaying information for each data point KirkmanJ 0 1,844 Jul-29-2019, 01:10 PM
Last Post: KirkmanJ
  Encapsulation issue iFunKtion 4 3,948 Mar-07-2017, 10:13 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020