I am quite confused with the method and attribute of a Python class. Suppose we have a Python class like this:
# case 1
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
self.fun()
def fun(self):
value = self.first + '---' + self.last
self.fun = value
return value
person_1 = Person('A', 'B')
person_1.fun
---> "A---B"
As we can see, in case_1 we initialize an instance person_1
. And we can get the result we want by calling fun
as an attribute. However, if we change our code to the following, fun
becomes a method instead.(case_2)
# case 2
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
self.fun()
def fun(self):
value = self.first + '---' + self.last
return value
person_1 = Person('A', 'B')
person_1.fun
---> <bound method Person.fun of <__main__.Person object at 0x7fd4f79168d0>>
We still contain the init process in the class. But now fun
becomes a method but not an attribute. (case_2)
If we remove the self.fun()
in init
but keep the self.fun = value
, it is still a method. (case_3)
# case 3
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
def fun(self):
value = self.first + '---' + self.last
self.fun = value
return value
person_1 = Person('A', 'B')
person_1.fun
---> <bound method Person.fun of <__main__.Person object at 0x7fd4f797f390>>
Would you mind giving me some instructions about why this happens? And what is the proper way to use the function as an attribute inside a Python Class? Thank you so much in advance!
In case 1, your constructor calls fun() which has a line inside of it to overwrite itself with an attribute value. This is confusing and not a good thing to do because it is confusing.
In case 2, your fun method does not include the line to overwrite itself so it doesn't get overwritten.
In case 3, you never actually call your fun method so it never has a chance to overwrite itself. If you called it with person_1.fun() i.e. with parentheses, then it would execute and overwrite itself and from that point on, person_1.fun would be an attribute value.
Remember that in python, a function/method ONLY executes if it is called with parentheses. If you don't express it with parentheses, then the result of evaluation is not the output of the function, but instead the expression produces a reference to the function itself, which can be put in another variable or in a data structure and called later.
To illustrate this:
>>> def my_func():
... print('got called')
... return 42
...
>>> x = my_func #no parentheses, x becomes an alias to my_func
>>> y = my_func() #parentheses means actually execute
got called
>>> y
42
>>> x
<function my_func at 0x765e8afdc0>
>>> x() #x is a reference to my_func and can be called itself
got called
42
>>>