Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
classes
#1
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?
Reply
#2
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
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#3
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.
Reply
#4
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
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
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.
Reply
#6
(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
Reply
#7
(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
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
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
pyzyx3qwerty
"The greatest glory in living lies not in never falling, but in rising every time we fall." - Nelson Mandela
Need help on the forum? Visit help @ python forum
For learning more and more about python, visit Python docs
Reply
#9
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?
Reply
#10
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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Using classes? Can I just use classes to structure code? muteboy 5 5,117 Nov-01-2017, 04:20 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

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