0

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()
Trenton McKinney
63.2k41 gold badges170 silver badges214 bronze badges
asked Jan 12, 2022 at 17:36
3
  • Employee.f_salary and Employee.display are just functions, not methods that already have an instance of Employee bound to the self parameter of the underly function. Commented Jan 12, 2022 at 17:40
  • How do you expect Employee.f_salary() to "know" it has to compute the salary for John Smith? Commented Jan 12, 2022 at 17:40
  • Suppose you had two instances of Employee: how do you think Employee.f_salary(), for example, would know whose salary to print? Commented Jan 12, 2022 at 17:41

3 Answers 3

7

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.

answered Jan 12, 2022 at 17:38
Sign up to request clarification or add additional context in comments.

Comments

0

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()
answered Jan 12, 2022 at 17:39

1 Comment

Thanks! it was a very silly mistake and I am still learning.
0

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).

answered Jan 12, 2022 at 17:47

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.