¿Cómo se sabe al observar la lista de atributos y métodos enumerados en un Dir que son atributos y cuáles son los métodos?

StackOverflow https://stackoverflow.com/questions/880160

Pregunta

Estoy trabajando tratando de aprender a programar en Python y estoy enfocado en obtener un mejor manejo de cómo usar los módulos estándar y otros. La función Dir parece realmente poderosa en el intérprete, pero me pregunto si me estoy perdiendo algo por mi falta de antecedentes de OOP. Usando el libro de S.Lotts, decidí usar su clase Die para aprender más sobre la sintaxis y el uso de clases e instancias.

Aquí está el código original:

class Die(object):
''' simulate a six-sided die '''
def roll(self):
    self.value=random.randrange(1,7)
    return self.value
def getValue(self):
    return self.value

Estaba mirando eso y después de crear algunas instancias, me pregunté si el valor de la palabra era una palabra clave de alguna manera y qué hizo el uso del objeto de la palabra en la declaración de clase, por lo que decidí averiguar cambiando la definición de clase a lo siguiente:

class Die():
''' simulate a six-sided die '''
def roll(self):
    self.ban=random.randrange(1,7)
    return self.ban
def getValue(self):
    return self.ban

Ese cambio me mostró que obtuve el mismo comportamiento de mis instancias, pero faltaban los siguientes métodos/atributos en los casos en que hice DIR:

'__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
 '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
_repr__', '__setattr__', '__str__', '__weakref__'

También descubrí que cuando hice un directorio en una instancia tenía una palabra clave adicional.prohibición Lo cual finalmente descubrí que era un atributo de mi instancia. Esto me ayudó a entender que podría usar D1.ban Para acceder al valor de mi instancia. La única razón por la que pude entender que este era un atributo fue que escribí d1.Happy y tengo un Atributoerror Me di cuenta de que d1.getValue Era un método adjunto para morir porque eso es lo que me dijo el intérprete.

Entonces, cuando estoy tratando de usar un módulo complicado pero útil como Beautifulsoup, ¿cómo puedo saber cuál de las cosas que se enumeran son atributos de mi instancia o métodos de mi instancia después de escribir? dir (instancia). Necesitaría saber esto porque este hurgado me ha enseñado que con los atributos llamo el resultado de un método y con los métodos estoy invocando una función en mi instancia.

Esta pregunta es probablemente demasiado prolongada, pero seguro que me ayudó a comprender mejor la diferencia entre atributos y métodos. Específicamente, cuando miro el resultado de llamar a Dir en una instancia de mi clase de die, veo esto

['__doc__', '__module__', 'ban', 'getValue', 'roll']

Por lo tanto, parecería útil saber al observar esa lista que son atributos y que son métodos sin tener que recurrir a la prueba y el error o el resultado de escribir Hasattr (myInstance, sospecheTtributeName).

Después de publicar la pregunta que probé

for each in dir(d1):
    print hasattr(d1,each)

Lo que me dice estrictamente hablando que todos los métodos son atributos. Pero no puedo llamar a un método sin el () Entonces me parece que el Hasattr () es engañoso.

¿Fue útil?

Solución

En vez de: "print hasattr(d1,each)", probar: "print each, type(getattr(d1,each))". Debe encontrar los resultados informativos.

Además, en lugar de dir() probar help(), que creo que realmente estás buscando.

Otros consejos

Considere usar la biblioteca estándar inspect Módulo: a menudo es el enfoque más práctico para la introspección, empaquetar fragmentos sustanciales de funcionalidad (podría implementarlo desde cero, pero reutilizar el código bien probado y bien diseñado es algo bueno). Ver http://docs.python.org/library/inspect.html Para todos los detalles, pero por ejemplo inspect.getmembers(foo, inspect.ismethod) es una excelente manera de obtener todos los métodos de foo (obtendrás (name, value) pares ordenados por nombre).

Lo que me dice estrictamente hablando que todos los métodos son atributos. Pero no puedo llamar a un método sin el (), por lo que me parece que el Hasattr () es engañoso.

¿Por qué es engañoso? Si obj.ban() es un método, entonces obj.ban es el atributo correspondiente. Puedes tener código como este:

print obj.getValue()

o

get = obj.getValue
print get()

Si desea obtener una lista de métodos en un objeto, puede probar esta función. No es perfecto, ya que también activará atributos invocables que no son métodos, pero para el 99% de los casos deben ser lo suficientemente buenos:

def methods(obj):
    attrs = (getattr(obj, n) for n in dir(obj))
    return [a for a in attrs if a.hasattr("__call__")]

Este info El módulo inspirado de bucear en pitón sirve al propósito.

def info(obj, spacing=20, collapse=1, variables=False):
    '''Print methods and their doc Strings

    Takes any object'''
    if variables:
    methodList = [method for method in dir(obj)]
    else:
    methodList = [method for method in dir(obj) if callable(getattr(obj,method))]

    #print methodList


    print '\n'.join(['%s %s' %
            (method.ljust(spacing),
             " ".join(str(getattr(obj,method).__doc__).split()))
            for method in methodList])


if __name__=='__main__':
    info(list)

Hay un método incorporado llamado Callable. Puede aplicarlo a cualquier objeto y devolverá verdadero/falso dependiendo de si se puede llamar. p.ej

>>> def foo():
...   print "This is the only function now"
...
>>> localDictionary = dir()
>>> for item in localDictionary:
...   print repr(item) + "is callable: " + str(callable(locals()[item]))
'__builtins__'is callable: False
'__doc__'is callable: False
'__name__'is callable: False
'foo'is callable: True

Tenga en cuenta que la llamada locales () devolverá un diccionario que contenga todo definido en su alcance actual. Hice esto porque los elementos fuera del diccionario son solo cuerdas, y necesitamos ejecutar llamables en el objeto real.

Idealmente, cuando usa una biblioteca complicada como BeautifulSoup, debe consultar su documentación para ver qué métodos proporciona cada clase. Sin embargo, en el raro caso en el que no tiene documentación de fácil acceso, puede verificar la presencia de métodos utilizando lo siguiente.

Todos los métodos, que son objetos, implementan el __call__ método y se puede verificar utilizando el método Callable () que devuelve True, si el valor que se verifica tiene el __call__ método.

El siguiente código debería funcionar.

x = Die()
x.roll()

for attribute in dir(x) :
    print attribute, callable(getattr(x, attribute))

El código anterior devolvería verdadero para todos los métodos y falsos para todos los atributos no llamables (como miembros de datos como BAN). Sin embargo, este método también devuelve True para cualquier objeto invocado (como clases internas). También puede verificar si el tipo de atributo es instancemethod

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top