why does this print "So it must be: test test" and not "So it must be: hello it's me"
class bob():
subjectTemp='test'
levelTemp='test'
def setSubject(function_subject):
bob.subjectTemp=function_subject
print(bob.subjectTemp)
def setLevel(function_level):
bob.levelTemp=function_level
print(bob.levelTemp)
def join(subject=subjectTemp, level=levelTemp):
print("So it must be:", subject, level)
bob.setSubject("hello")
bob.setLevel("it's me")
bob.join()
CodePudding user response:
The immediate "problem" is that this binds at function definition time:
def join(subject=subjectTemp, level=levelTemp):
The value of subject
will be the value of subjectTemp
at the time the function was declared, and it won't change. See "Least Astonishment" and the Mutable Default Argument for details.
The bigger problem is that this isn't how you use classes at all. You want something like this:
class Bob():
subject = 'test'
level = 'test'
def set_subject(self, subject):
self.subject = subject
print(self.subject)
def set_level(self, level):
self.level = level
print(self.level)
def join(self):
print("So it must be:", self.subject, self.level)
b = Bob()
b.set_subject("hello")
b.set_level("it's me")
b.join()
CodePudding user response:
The default values are evaluated, once, at function definition. This is a classic problem that new Pythonistas stumble upon when using mutable arguments such as lists — but this is another instance of the same gotcha.
You can read more about default arguments in the official documentation.
In particular: "Important warning: The default value is evaluated only once".
Edit: This is the technical explanation for what you ask about, but please read others' comments and answers here. This is a peculiar way to use Python classes which will probably trip your leg down the road. Please google 'Pythonic code' and 'idiomatic code'.
CodePudding user response:
subjectTemp and levelTemp have the default value.
You can write:
class bob():
subjectTemp='test'
levelTemp='test'
def setSubject(function_subject):
bob.subjectTemp=function_subject
print(bob.subjectTemp)
def setLevel(function_level):
bob.levelTemp=function_level
print(bob.levelTemp)
def join():
print("So it must be:", bob.subjectTemp, bob.levelTemp)
bob.setSubject("hello")
bob.setLevel("it's me")
bob.join()
CodePudding user response:
First, your code looks strange, I don't know why you wrote it in that way but why not?
class Bob: #Capitalized Class
subjectTemp='test'
levelTemp='test'
@staticmethod # if you don't need 'self'
def set_subject(function_subject): # not camelcase, use undercore
bob.subjectTemp=function_subject
print(bob.subjectTemp)
@staticmethod
def set_level(function_level):
bob.levelTemp=function_level
print(bob.levelTemp)
@staticmethod
def join(subject=subjectTemp, level=levelTemp):
print("So it must be:", subject, level)
bob = Bob()
bob.setSubject("hello")
bob.setLevel("it's me")
bob.join()
Another thing is that is a difference between class attributes and instance attributes, I think that, when you use bob.subjectTemp
you are changing the instance attribute and when you refer subjectTemp, you are calling class attribute.
Then, your code for works, maybe can looks like:
class Bob:
subject_temp='test'
level_temp='test'
def set_subject(self, function_subject):
self.subject_temp=function_subject
print(self.subject_temp)
def set_level(self, function_level):
self.level_temp=function_level
print(self.level_temp)
def join(self, subject=None, level=None):
if subject is None:
subject = self.subject_temp
if level is None:
level = self.level_temp
print("So it must be:", subject, level)
bob = Bob()
bob.set_subject("hello")
bob.set_level("it's me")
bob.join()