Reputation: 106
This python program was designed to find the area and circumference of a circle, but for some reason, I'm getting a TypeError: 'float' object is not callable
error when I'm trying to execute the area method.
class Circle:
pi = 3.14
def __init__(self, radius=1):
self.radius = radius
self.area = radius * radius * self.pi
def circum(self):
return self.pi * self.radius * 2
my_circle = Circle(30)
my_circle.area()
Error
Traceback (most recent call last):
File "test.py", line 13, in <module>
my_circle.area()
TypeError: 'float' object is not callable
Upvotes: 0
Views: 5685
Reputation: 1815
I want to explain meaning of error. In python there are callable and non callables. Not only functions but also instances of classes can be callable.
float object is not callable (self.area is float). A class is callable if it has __call__
method defined.
1.1()
TypeError: 'float' object is not callable
You will get the same error if you call 1.1() . Because 1.1 is of type float and float does not have __call__
method.
Look at example below
class callable_area(float):
def __call__(self, x):
print('My parent is float and can not be called, but i can be')
print(self * x)
# Product of two numbers
callable_area(1.1)(2.2)
callable_area(1.1)
is not a function and is instance of class, but still i can call it like this callable_area(1.1)(2.2)
.
Now maybe the error you get is just a unconscious mistake and you convert it into function or remove empty brackets infront of it and remove error, but it is also good idea to know what error is implying
Upvotes: 0
Reputation: 19312
It's quite straightforward where the issue is. self.area
is a variable that is being stored and initialized in the object, not a function. Therefore you can just access it without using ()
at the end which is used for a function call (or initializing objects of a class, see additional note). Check the code and comments below.
Additional Note: You will see the use of
Circle(30)
to initialize an object. This convention is used to pass parameters to the__init__
function inside the class while instantiating an object, and it looks the same as if calling a function!
class Circle:
pi = 3.14
def __init__(self, radius=1):
self.radius = radius
self.area = radius * radius * self.pi
def circum(self):
return self.pi * self.radius * 2
my_circle = Circle(30)
#View all the variables initialized in your object
my_circle.__dict__
>>{'radius': 30, 'area': 2826.0}
#Fetch a variable
my_circle.area
>>2826.0
#Call a function
my_circle.circum()
>>188.4
Based on what you mention in description this is how you should ideally defined the class you are mentioning -
class Circle:
def __init__(self, radius=1):
self.pi = 3.14
self.radius = radius
def circum(self):
self.circum = self.pi * self.radius * 2
print(self.circum)
def area(self):
self.area = self.radius * self.radius * self.pi
print(self.area)
circle = Circle(30)
#Only radius defined till now
circle.__dict__
#>>{'pi': 3.14, 'radius': 30}
circle.circum()
#>>188.4
circle.area()
#>>2826.0
#After calling the 2 functions, the self dict gets updated with area and circumference
circle.__dict__
#>>{'pi': 3.14, 'radius': 30, 'circum': 188.4, 'area': 2826.0}
The way I like to imagine objects of a class is that it is an object is a database with some optional explicit functions defined. The
__init__
function initialized the database. You can access everything that the database contains by using theself
. Therefore when you passself
to a function, you giving that function access to all of the database that the object is storing. To print everything in that databaseself
you can usemy_circle.__self__
Upvotes: 2
Reputation: 54645
Circle.area
is not a method. It is a simple variable. You can read it with my_circle.area
.
If you want it to be a function, so you can change the radius and recompute, then you need to make it a function.
def area(self):
return self.radius * self.radius * self.pi
Upvotes: 4