No entiendo este TypeError: el objeto ‘list’ no es un error que se puede llamar

Tengo un archivo llamado im.py que contiene un par de funciones y varias clases. La primera función y la clase están fallando con

 TypeError: 'list' object is not callable 

El problema parece ser el primer elemento de una lista creada en la función que luego se pasa a la clase. La clase puede procesar la mayor parte de la lista, pero el primer elemento no puede. La transición al espacio de nombres de clase parece ser el problema:

 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 

En la sesión interactiva todo está bien en la función:

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

Pero luego en la clase:

 >>> 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 "", line 1, in  TypeError: 'list' object is not callable 

Tan solo para recapitular:

 >>> type(b.user()) Traceback (most recent call last): File "", line 1, in  TypeError: 'list' object is not callable >>> type(a[0])  

Entonces está claro cuál es el problema. Simplemente no sé cómo la conversión de clase está enmascarando el primer elemento de la lista. ¿Algunas ideas?

No puede usar el mismo nombre para un método y un atributo; Los métodos son solo tipos especiales de atributos. Su clase puede tener un método de user() , pero al establecer el atributo user en la instancia, Python encontrará que en lugar del método cuando intenta acceder a b.user :

 >>> type(b.user) # no call, just the attribute  

Tendrá que cambiar el nombre del método o del atributo para no entrar en conflicto. Podría usar un guión bajo para el atributo de lista, por ejemplo:

 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 

Python no es como otros idiomas donde los campos y métodos pueden compartir el mismo nombre (como Java). En Python, cuando le asigna a un atributo de instancia el mismo nombre que a un método, el método lo oculta.

Sin embargo, en general, Python evita a los que obtienen y configuran, ya que no proporcionan los mismos beneficios en Python que en los lenguajes de tipo estático (como Java).

En Python, es más probable que hagas algo como:

 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)