0

I was tasked with creating a program using OOP, reading the documentation they gave me about this task, I have noticed many code examples that use this naming convention:

class User:
    def __init__(self, x, y, z):
        self.__x = x
        self.__y = y
        self.__z = z

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

    @property
    def y(self):
        return self.__y

    @property
    def z(self):
        return self.__z

Is this the pythonic way? I'd go instead with plain attributes, like this:

class User:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

I don't have much experience with OOP so maybe I'm missing something, in the first example, you have naming mangling protecting the attributes, but I don't know why it is even necessary, as far as I've seen all the modifications to the class attributes are only made within each class, and not from outside. Any ideas on why would the first example make more sense?

2
  • yes, it is....... Commented Dec 7, 2021 at 23:41
  • 1
    The True Pythonic Way™ would be to not use getters and setters at all unless there's a compelling reason to do so (since they can always be added later if the need arises without breaking any existing clients' code). Commented Dec 8, 2021 at 0:59

2 Answers 2

1

This pattern:

class User:
    def __init__(self, x, y, z):
        self.__x = x

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

Makes more sense if you want to expose x for reading, but don't want people accidentally setting it.

You can of course add a setter:

    @x.setter
    def x(self, value):
        self.__x_was_set = True
        self.__x = value

That makes more sense if you need some side effect of setting a property to occur (I added a trivial one with __x_was_set, but it could be anything and something quite complicated).

If you don't need either, just doing this makes more sense:

class User:
    def __init__(self, x):
        self.x = x

Or you could even use a dataclass:

@dataclass
class User:
    x: str

(or whatever type you need for x of course)

I find that developers coming from languages like Java or C# tend to overuse the getter/setter pattern, because it's what they're more used to. I'd say that just from a Python-perspective simpler and more readable is better. More so because reading and setting user.__x is still possible, so no actually protection is added, it's just adding code.

Sign up to request clarification or add additional context in comments.

Comments

1

If it's a private property for inner class usage, it's actually the way python is written its own classes and it's called private name mangling :

see The Python Language Reference for more information:

Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used. If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.