Python Forum
question about using setter, getter and _
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
question about using setter, getter and _
#1
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
Reply
#2
(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.
akbarza likes this post
« We can solve any problem by introducing an extra level of indirection »
Reply
#3
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.
akbarza likes this post
Reply
#4
(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?
Reply
#5
__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).
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python class doesn't invoke setter during __init__, not sure if's not supposed to? mtldvl 2 3,359 Dec-30-2021, 04:01 PM
Last Post: mtldvl
  how to use getter as argument in function nanok66 3 3,289 May-13-2020, 09:15 AM
Last Post: nanok66
  Getter/Setter : get parent attribute, but no Getter/Setter in parent nboweb 2 3,002 May-11-2020, 07:22 PM
Last Post: nboweb
  Setter of class object maitreyaverma 1 2,448 Sep-28-2017, 06:15 PM
Last Post: nilamo

Forum Jump:

User Panel Messages

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