Python Forum
question about using setter, getter and _ - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: question about using setter, getter and _ (/thread-41345.html)



question about using setter, getter and _ - akbarza - Dec-27-2023

hi
in below code:

# from: https://virgool.io/@GreatBahram/once-for-all-property-sovwcuakw7aq
# code about getter, setter
class Person:
    def __init__(self,username):
        self.username=username
    #getter
    @property
    def username(self):
        return self._username

    #setter
    @username.setter
    def username(self,name):
        if not isinstance(name,str):
            raise TypeError('name must be a string')
        self._username= name.lower()

        
p=Person('Ali')
p.username
# output will be : 'ali'
p.username='mohammad'
p.username
#output will be: 'mohammad'
what is differnce between username and _username or between self.username and slef._username?
plz, explain.
thanks


RE: question about using setter, getter and _ - Gribouillis - Dec-27-2023

(Dec-27-2023, 01:20 PM)akbarza Wrote: what is differnce between username and _username or between self.username and slef._username?
_username is just another attribute name. It could be replaced by any other name such as hidden_data
class Person:
    def __init__(self,username):
        self.username=username
    #getter
    @property
    def username(self):
        return self.hidden_data

    #setter
    @username.setter
    def username(self,name):
        if not isinstance(name,str):
            raise TypeError('name must be a string')
        self.hidden_data= name.lower()


p=Person('Ali')
print(p.username)
# output will be : 'ali'
p.username='mohammad'
print(p.username)
#output will be: 'mohammad'
In this code, the name is stored in the Person object as the member self.hidden_data. When the code using this class calls p.username, that value is returned by the property getter function. When the client code writes p.username = 'Mohammad' the value is converted to lower case and then stored in the object by the property setter function.

Client code is not supposed to access directly p.hidden_data, but the Python language does not forbid that. Therefore it is a convention among Python programmers that a variable which name starts with an underscore is not meant to be accessed directly by client code. It is a "private" variable known from the Person class but not from client code. That's why a name such as _hidden_data or _username is preferred.

Note that the statement self.username = username in the __init__() function invokes the property setter to check that the argument is a string and to store the lowercase value of this argument in the variable self.hidden_data.


RE: question about using setter, getter and _ - deanhystad - Dec-27-2023

It is a Python coding convention that attribute names starting with an underscore should be treated as private, and code outside the class should not access these variables. Think of it as a warning:

"I cannot stop you from referencing this attribute, but directly accessing the attribute is not how the class is designed to work. I won't feel any remorse when I change the design of this class in the future and remove this attribute that I warned you against using."

In your example, _username should not be referenced outside of the class. if you set the Person's username using the _username attribute you could break the rule that usernames are all lowercase. If this caused problems elsewhere in the code it would be all your fault because you didn't follow the rules (conventions) for using the class.

You might also see variable/attribute names that end in an underscore. This convention is used when the name you want to use conflicts with a Python keyword, a built-in function (next_ is one I often use) or some other name defined in your module.


RE: question about using setter, getter and _ - akbarza - Dec-28-2023

(Dec-27-2023, 04:26 PM)Gribouillis Wrote:
(Dec-27-2023, 01:20 PM)akbarza Wrote: what is differnce between username and _username or between self.username and slef._username?
_username is just another attribute name. It could be replaced by any other name such as hidden_data
class Person:
    def __init__(self,username):
        self.username=username
    #getter
    @property
    def username(self):
        return self.hidden_data

    #setter
    @username.setter
    def username(self,name):
        if not isinstance(name,str):
            raise TypeError('name must be a string')
        self.hidden_data= name.lower()


p=Person('Ali')
print(p.username)
# output will be : 'ali'
p.username='mohammad'
print(p.username)
#output will be: 'mohammad'
In this code, the name is stored in the Person object as the member self.hidden_data. When the code using this class calls p.username, that value is returned by the property getter function. When the client code writes p.username = 'Mohammad' the value is converted to lower case and then stored in the object by the property setter function.

Client code is not supposed to access directly p.hidden_data, but the Python language does not forbid that. Therefore it is a convention among Python programmers that a variable which name starts with an underscore is not meant to be accessed directly by client code. It is a "private" variable known from the Person class but not from client code. That's why a name such as _hidden_data or _username is preferred.

Note that the statement self.username = username in the __init__() function invokes the property setter to check that the argument is a string and to store the lowercase value of this argument in the variable self.hidden_data.

hi
you have said that :
Quote: Note that the statement self.username = username in the __init__() function invokes the property setter to check that the argument is a string and to store the lowercase value of this argument in the variable self.hidden_data
I ran the code and I saw that it changed names to lowercase and this is done in setter. but i do not understand why __init__ uses the setter . can explain?


RE: question about using setter, getter and _ - deanhystad - Dec-28-2023

__init_() uses the setter because the setter ensures that usernames are all lowercase. You could write the code like this:
    def __init__(self,username):
        self._username=username.lower()
But now you have two places in the code that process usernames. If you changed your code to make usernames uppercase you would have two places in the code you need to edit. Doing things in one place is always better than repeating the code in multiple places.

Next time really think things through before you post. I think you are so focused on the Python that you are not thinking about the design. Logically it is obvious that you would want the same rules to apply to username if it is the initial value (set in __init__()) or if it is changed at a later time (using property).