0

Usually in OOP world we are told that modularity is a good practice and keeping loose coupling between module is a great thing. Encapsulation helps us achieve this loose coupling.

In Java encapsulation is achieved via access modifiers, in Ruby we have stricter rules via attr_accessor.

But what about Python? I see that I can't hide my fields or methods except using tricks like __ in front of names. Is this the correct / only way to achieve encapsulation in Python?

  • why do you feel like you need to hide your fields or methods? – Bryan Oakley Dec 20 '15 at 17:10
  • @BryanOakley for the same reason we do in Java or Ruby. – CodeYogi Dec 24 '15 at 5:10
6

Take a look at the following C++ code:

#include<iostream>
using namespace std;

class Foo {
    private:
        int x;

    public:
        Foo(int x): x(x) {}

        void printX() {
            cout << "My x is " << x << endl;
        }
};

int main(int argc, char** argv) {
    Foo foo(12);
    foo.printX(); // prints "My x is 12"

    //foo.x = 13; // error: ‘int Foo::x’ is private

    *((int*) &foo) = 14;
    foo.printX(); // prints "My x is 14"

    return 0;
}

I've broken the encapsulation by casting a pointer. Does that mean encapsulation is broken in C++? No - because no one in their right mind would do that! Cast at your own risk.

It's the same with Python - use fields prefixed with _ at your own risk. Encapsulation is for safety - not for security. You don't put private keys in private fields and trust the encapsulation to prevent users from touching them. You use encapsulation to protect the users of your classes from internal implementation details - and if these users don't respect Python's convention it's their own damn problem.

  • 1
    Why this freedom in Python only? why not in Java or any statically typed language? Also, one thing seems quite disturbing to me that in python any client code can change the Shape of the object any time hence creating havoc. – CodeYogi Nov 20 '15 at 5:24
  • The whole idea of encapsulation seems useless in python.If I agree to you because the power now lies in the hands of client code not in your hands. – CodeYogi Nov 20 '15 at 5:25
  • 3
    If the client wants he can throw out entire classes and replace them by new ones. The Python philosophy is that we're all consenting adults and can use our own judgement. – RemcoGerlich Dec 20 '15 at 13:32
  • "Encapsulation is for safety - not for security" — good one :) – synthomat Dec 23 '15 at 10:28
0

You can use @property annotations to implement getters and setters à la Java or Ruby. These provide some form of encapsulation while still allowing users of your class to access attributes in a Pythonic way.

Say you have a class with a public-facing name attribute, but names needed to be under a certain length.

class Foo(object):

    def __init__(self, name: str):
        if len(name) <= 3:
            self.name = name
        else:
            raise TypeError

In this case, the name value length is checked at instantiation but not thereafter; you could use a _name attribute and ugly get_name() and set_name() methods, but by using @property annotations as below, you can do validity checking for the attribute whenever it's set while still letting it be accessed in the conventional Python way, i.e. by means of expressions like foo.name and foo.name = 'xyz'.

class Foo(object):

    def __init__(self, name: str):
        self.name = name

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

    @name.setter
    def name(self, new_name: str):
        if len(new_name) <= 3:
            self._name = new_name
        else:
            raise TypeError

As Idan mentioned, _-prefixing of private methods/attributes is just a (strongly followed) convention and a user could still mangle the attribute value if they really wanted to, e.g. by foo._name = 'abcdef'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.