I was making a python class in which it has an employee's name, salary, and the number of leaves as attributes and was trying to show the final salary of an employee deducting the salary for the days he/she has not come but it is showing an error. The error is:
TypeError: Employee.f_salary() missing 1 required positional argument: 'self'
I had written the code:
class Employee:
def __init__(self, name, salary, no_of_leaves):
self.name = name
self.salary = salary
self.no_of_leaves = no_of_leaves
def f_salary(self):
self.f_salary1 = self.salary - 500 * int(self.no_of_leaves)
def display(self):
print(f"Employee's name: {self.name}\nEmployee's monthly salary:
{self.salary}\nNo.of leaves that employee has taken: {self.no_of_leaves}")
nol = input("No. of leaves the employee has taken: ")
john_smith = Employee('John Smith', 182500, nol)
Employee.f_salary()
Employee.display()
3 Answers 3
You should call the method on the instance not the class object.
john_smith.f_salary()
john_smith.display()
Because the self parameter is a reference to the class instance which called the method in the first place.
Comments
The issue is you call the method on the class instead of the object you created.
Employee.f_salary()
Employee.display()
This can be easily fixed by using the object name.
john_smith.f_salary()
john_smith.display()
You can however pass self explicitly though if you use the class to call a method.
class Foo:
def bar(self):
# Etc.
some_foo = Foo()
# These are more or less equivalent if we assume no class extends Foo
Foo.bar(some_foo)
some_foo.bar()
1 Comment
Instance methods are just class attributes. Employee.f_salary is a reference to a function that requires a single argument.
john_smith.f_salary, though, is more interesting. Because function objects implement the descriptor protocol, accessing the value as an attribute of something always triggers its __get__ method, so that
Employee.f_salary == Employee.__dict__['f_salary'].__get__(None, Employee)
john_smith.f_salary == Employee.__dict__['f_salary'].__get__(john_smith, Employee)
In the first case, __get__ simply returns the function itself, so when you try to call it, it still expects an argument for its self parameter.
In the second case, __get__ returns an instance of the method class, which internally keeps two references: one to john_smith, and one to the function itself.
When you try to call the method object, it simply takes its own arguments and passes them, along with john_smith, to the underlying function.
As such, john_smith.f_salary() returns the value of Employee.f_salary(john_smith).
Comments
Explore related questions
See similar questions with these tags.
Employee.f_salaryandEmployee.displayare just functions, not methods that already have an instance ofEmployeebound to theselfparameter of the underly function.Employee.f_salary()to "know" it has to compute the salary for John Smith?Employee: how do you thinkEmployee.f_salary(), for example, would know whose salary to print?