Python Forum
classes - 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: classes (/thread-27255.html)

Pages: 1 2


classes - mp3909 - May-31-2020

So I am learning classes in python and I stumbled across something that did not make sense to me.
In the code below, when I change the name of the student via calling the method changeName passing the new parameters (forename and surname), why doesn't it reflect the changes when I print the attribute fullname?

class Student:

    def __init__(self, forename, surname):
        self.forename = forename
        self.surname = surname
        self.fullname = self.forename + " " + self.surname

    def changeName(self, forename, surname):
        self.forename = forename
        self.surname = surname

s1 = student("billy", "smith")
print(s1.fullname)
s1.changename("tom", "jones")
print(s1.fullname)              ----> why is this not updating?



RE: classes - menator01 - May-31-2020

Check your spelling
your not return fullname in changeName

class Student:
    def __init__(self, forename, surname):
        self.forename = forename
        self.surname = surname
        self.fullname = self.forename + " " + self.surname

    def changeName(self, forename, surname):
        self.forename = forename
        self.surname = surname
        self.fullname = f'{self.forename} {self.surname}'
        return self.fullname


s1 = Student('Billy','Smith')
print(s1.fullname)
s1.changeName('Tom','Jones')
print(s1.fullname)
Output:
Billy Smith Tom Jones



RE: classes - mp3909 - May-31-2020

There's nothing grammatically wrong with the spelling in my code.

You pointed out that I need to declare self.fullname again in the method and then it works. Although you are correct, it just doesn't make any sense since all that the self.fullname does is basically print out the values of self.forename and self.surname and these are being changed in the method so I would have thought python would be smart enough to work with the latest values assigned to these attributes, hence i was expecting self.fullname to print out the updated name without the need to explicitly declare it again.


RE: classes - buran - May-31-2020

fullname is property like any other, it's not linked to forename and surname (i.e. updated when forname and surname change)
To achieve what you want you need to use @property decorator in this case and get the Student.fullname from Student.forename and Student.surname. Also, note that you don't really need changeName method.

class Student:
    def __init__(self, forename, surname):
        self.forename = forename
        self.surname = surname

    @property
    def fullname(self):
        return f"{self.forename} {self.surname}" # using f-string or str.format() is better than string concatenation"
 
    def change_name(self, forename, surname):
        self.forename = forename
        self.surname = surname

s1 = Student('Billy','Smith')
print(s1.fullname)
s1.change_name('Tom','Jones')
print(s1.fullname)
# no need of change_name
s1.forename = 'Jake'
print(s1.fullname)
s1.fullname = 'Jane Doe'
Output:
Billy Smith Tom Jones Jake Jones Traceback (most recent call last): File "/home/boyan/sandbox2/forum.py", line 23, in <module> s1.fullname = 'Jane Doe' AttributeError: can't set attribute
as you can see, now you cannot change fullname directly


RE: classes - deanhystad - May-31-2020

The problem is caused by not executing the code that generates fullname.

One way to solve this problem is to recompute fullname any time you change forename or surname (duplicate some code from the init method). Another solution is to recompute fullname any time you ask for it.
    def __init__(self, forename, surname):
        self.forename = forename
        self.surname = surname

    def fullname()
        return self.forename + " " + self.surname
If you want fullname to look like a class variable instead of a function you can use a property decorator.
@property
def fullname()
    return self.forename + " " + self.surname
A nice thing about this approach is that fullname is guaranteed to always be forename followed by surname. Unlike the original code a user of your class cannot set the fullname independently of the forename or surname.


RE: classes - Yoriz - May-31-2020

(May-31-2020, 02:02 PM)buran Wrote: as you can see, now you cannot change fullname directly

Unless you wanted to add a setter then you could change fullname like this.
class Student:
    def __init__(self, forename, surname):
        self.forename = forename
        self.surname = surname
 
    @property
    def fullname(self):
        return f"{self.forename} {self.surname}" # using f-string or str.format() is better than string concatenation"

    @fullname.setter
    def fullname(self, full_name):
        self.forename, self.surname = full_name.split(' ')
  

s1 = Student('Billy','Smith')
print(s1.fullname)
s1.fullname = 'Tom Jones'
print(s1.fullname)
s1.forename = 'Jake'
print(s1.fullname)
s1.fullname = 'Jane Doe'
print(s1.fullname)
Output:
Billy Smith Tom Jones Jake Jones Jane Doe



RE: classes - buran - May-31-2020

(May-31-2020, 03:51 PM)Yoriz Wrote: Unless you wanted to add a setter then you could change fullname like this.
yes, of course, one can create setter and manipulate forename and surname respectively. Good point


RE: classes - pyzyx3qwerty - Jun-01-2020

Also remember - once you define something in python you got to use the exact same word with changing anything in its structure - Python is sensitive about that


RE: classes - mp3909 - Jun-09-2020

Ok, thanks guys, much appreciated.

I seen elsewhere that the property decorators are ditched and written like this sometimes:

class C(object):
       def getx(self): return self._x
       def setx(self, value): self._x = value
       def delx(self): del self._x
       x = property(getx, setx, delx, "I'm the 'x' property.")
I was trying to write the below code using the above implementation but not sure how?

class Employee:

    def __init__(self, first, last):
        self.first = first
        self.last = last

    @property
    def fullname(self):
        return f"{self.first} {self.last}"
    
    @fullname.setter
    def fullname(self, name):
        first, last = name.split(" ")
        self.first = first
        self.last = last

    @fullname.deleter
    def deleter(self):
        print("Delete Name")
        self.first = None
        self.last = None


emp_1 = Employee("john", "smith")
emp_1.fullname = "bill adams"
print(emp_1.first)
print(emp_1.last)
print(emp_1.fullname)
Also, which implementation is most widely used in practice?


RE: classes - deanhystad - Jun-10-2020

Getters and setters are nice when binding your code to events. I haven't found a good way to use properties in GUI code. It may not be "Pythonic", but neither are Qt or GTK or Tk.