Reputation: 31
I have file called im.py
which contains a couple of functions and several classes. The first function and class are failing with
TypeError: 'list' object is not callable
The problem appears to be the first element of a list created in the function which is then passed to the class. Most of the list can be processed by the class, but the first element cannot. The transition to the class name space seems to be the problem:
def getdata_user():
import os
user = os.getlogin()
gids = os.getgroups()
home = os.getenv('HOME')
return [user, gids, home]
class FirstClass:
def setdata_user(self):
self.user = getdata_user()
def displaydata_user(self):
print(self.user)
def user(self):
u = self.user[0]
return u
def gids(self):
g = self.user[1]
return g
def home(self):
h = self.user[2]
return h
In the interactive session all is well in the function:
>>> from im import *
>>> a = getdata_user()
>>> print(a)
['fred', [4, 24, 27, 30, 46, 109, 125, 1000], '/home/fred']
>>> print(a[0])
jreese
>>> print(a[1])
[4, 24, 27, 30, 46, 109, 125, 1000]
>>> print(a[2])
/home/fred
But then in the class:
>>> b = FirstClass()
>>> b.setdata_user()
>>> print(b.home())
/home/jreese
>>> print(b.gids())
[4, 24, 27, 30, 46, 109, 125, 1000]
>>> print(b.user())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
So just to recap:
>>> type(b.user())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
>>> type(a[0])
<class 'str'>
So it's clear what is the problem. I just don't know how the class conversion is masking the first element of the list. Any ideas?
Upvotes: 0
Views: 2095
Reputation: 40683
Python is not like some other languages where fields and methods can share the same name (such as Java). In Python when you give an instance attribute the same name as a method, the method is hidden by the attribute.
However, in general python eschews getters and setters as they do not provide the same benefits in Python as they do in statically typed languages (such as Java).
In Python, you would be more likely to do something like:
class FirstClass:
def setdata_user(self):
data = getdata_user()
self.user = data[0]
self.gids = data[1]
self.home = data[2]
# or more simply
self.user, self.gids, self.home = getdata_user()
def displaydata_user(self):
print([self.user, self.gids, self.home])
obj = FirstClass()
obj.setdata_user()
obj.displaydata_user()
# accessing individual attributes
print("user:", obj.user)
print("gids:", obj.gids)
print("home:", obj.home)
Upvotes: 1
Reputation: 1121216
You cannot use the same name for both a method and an attribute; methods are just special kinds of attributes. Your class may have a user()
method, but by setting the attribute user
on the instance, Python will find that instead of the method when you try to access b.user
:
>>> type(b.user) # no call, just the attribute
<class 'list'>
You'll have to rename either the method or the attribute to not conflict. You could use a leading underscore for the list attribute, for example:
class FirstClass:
def setdata_user(self):
self._user = getdata_user()
def displaydata_user(self):
print(self._user)
def user(self):
u = self._user[0]
return u
def gids(self):
g = self._user[1]
return g
def home(self):
h = self._user[2]
return h
Upvotes: 3