4. Introspecção

Um código Python pode fazer e responder perguntas sobre si mesmo e sobre os objetos que ele manipula.

4.1. dir()

dir() é uma função predefinida que retorna uma lista de todos os nomes pertencentes a algum espaço de nomes (namespace).

  • Se nenhum argumento for passado para dir (isto é, dir()), ele inspeciona o namespace no qual foi chamado.

  • Se dir receber um argumento (ou seja, dir(<object>), ele inspeciona o namespace do objeto que foi passado.

Por exemplo:

dir()
['In',
 'Out',
 '_',
 '_1',
 '_10',
 '_11',
 '_12',
 '_13',
 '_17',
 '_2',
 '_3',
 '_5',
 '_6',
 '_7',
 '_8',
 '_9',
 '__',
 '___',
 '__builtin__',
 '__builtins__',
 '__doc__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 '_dh',
 '_i',
 '_i1',
 '_i10',
 '_i11',
 '_i12',
 '_i13',
 '_i14',
 '_i15',
 '_i16',
 '_i17',
 '_i18',
 '_i2',
 '_i3',
 '_i4',
 '_i5',
 '_i6',
 '_i7',
 '_i8',
 '_i9',
 '_ih',
 '_ii',
 '_iii',
 '_oh',
 'a',
 'b',
 'exit',
 'get_ipython',
 'macas',
 'math',
 'my_int',
 'nome',
 'quit']
nome = "Pedro"
dir(nome)
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmod__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'capitalize',
 'casefold',
 'center',
 'count',
 'encode',
 'endswith',
 'expandtabs',
 'find',
 'format',
 'format_map',
 'index',
 'isalnum',
 'isalpha',
 'isdecimal',
 'isdigit',
 'isidentifier',
 'islower',
 'isnumeric',
 'isprintable',
 'isspace',
 'istitle',
 'isupper',
 'join',
 'ljust',
 'lower',
 'lstrip',
 'maketrans',
 'partition',
 'replace',
 'rfind',
 'rindex',
 'rjust',
 'rpartition',
 'rsplit',
 'rstrip',
 'split',
 'splitlines',
 'startswith',
 'strip',
 'swapcase',
 'title',
 'translate',
 'upper',
 'zfill']

4.1.1. Nomes Mágicos

Você encontrará muitos nomes que começam e terminam com um sublinhado duplo (por exemplo, __name__). Estes são chamados de nomes mágicos. Funções com nomes mágicos fornecem a implementação de funcionalidades particulares da linguagem Python.

Por exemplo, a aplicação de str a um objeto a, ou seja str(a), resultará - internamente - na chamada do método a.__str__(). O método __str__ geralmente precisa retornar uma string. A ideia é que o método __str__() deve ser definido para todos os objetos (incluindo aqueles que derivam de novas classes que um programador pode criar) de modo que todos os objetos (independentemente de seu tipo ou classe) pode ser impresso usando a função str(). A conversão real de algum objeto x para a string é então feita através do método específico do objeto x.__str__().

Podemos demonstrar isso criando uma classe my_int que herda da classe base de número inteiro do Python e substitui o método __str__. (Isto requer mais conhecimento de Python do que o fornecido até este ponto no texto para poder entender este exemplo.)

class my_int(int): 
    """Herdada de int""" 
    def __str__(self): 
        """ Representacao adaptada de str para a classe my_int""" 
        return "my_int: %s" % (int.__str__(self))
 
a = my_int(3)
b = int(4)            # equivalente a b = 4
print("a * b = ", a * b)
print("Type a = ", type(a), "str(a) = ", str(a))
print("Type b = ", type(b), "str(b) = ", str(b))
a * b =  12
Type a =  <class '__main__.my_int'> str(a) =  my_int: 3
Type b =  <class 'int'> str(b) =  4

4.1.1.1. Leitura complementar

Veja Documentação Python, Modelos de Dados

4.2. Tipo (type)

O comando type(<object>) retorna o tipo de um objeto:

type(1)
int
type(1.0)
float
type("Python")
str
import math
type(math)
module
type(math.sin)
builtin_function_or_method

4.3. isinstance

isinstance(<object>, <typespec>) retorna verdadeiro (True) se o objeto passado é uma instância do tipo de dado passado, ou de qualquer uma de suas superclasses. Use help(isinstance) para a sintaxe completa.

isinstance(2,int)
True
isinstance(2.,int)
False
isinstance(a,int)    # a é uma instância de my_int
True
type(a)
__main__.my_int

4.4. Obtendo ajuda com help

  • A função help reportará o docstring (atributo mágico com nome __doc__ do objeto que é passado, às vezes complementado com informação adicional. No caso de funções, help também mostrará a lista de argumentos que a função aceita (mas não fornecerá o valor de retorno).

  • help() inicializa um ambiente interativo de ajuda.

  • É comum usar o comando help muitas vezes para se lembrar da sintaxe e semântica dos comandos.

help(isinstance)
Help on built-in function isinstance in module builtins:

isinstance(obj, class_or_tuple, /)
    Return whether an object is an instance of a class or of a subclass thereof.
    
    A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to
    check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)
    or ...`` etc.
import math
help(math.sin)
Help on built-in function sin in module math:

sin(...)
    sin(x)
    
    Return the sine of x (measured in radians).

A função help depende do nome de um objeto (que deve existir no espaço de nomes corrente). Por exemplo, help(math.sqrt) não funcionará se o módulo math não tiver sido importado antes.

del math # desligando o modulo math (omp anteriormente) para destacar o erro.
help(math.sqrt) 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-33-e3a778a8af20> in <module>()
      1 del math
----> 2 help(math.sqrt) # reinicie o kernel e execute esta célula antes das demais para perceber o erro.

NameError: name 'math' is not defined
import math
help(math.sqrt)
Help on built-in function sqrt in module math:

sqrt(...)
    sqrt(x)
    
    Return the square root of x.

Em vez de importar o módulo, poderíamos ter também passado a string math.sqrt para a função help, i.e.:

help('math.sqrt')
Help on built-in function sqrt in math:

math.sqrt = sqrt(...)
    sqrt(x)
    
    Return the square root of x.
  • help é uma função que fornece informações sobre o objeto que é passado como seu argumento. A maioria das coisas em Python (classes, funções, módulos, etc.) são objetos e, por isso, podem ser passados para a função help. Há, no entanto, algumas coisas para as quais você gostaria de ajuda, mas que não são objetos existentes em Python. Nesses casos, muitas vezes é possível passar uma string contendo o nome da coisa ou conceito para a função help, por exemplo.

  • help('modules') gerará uma lista de todos os módulos que podem ser importados para o interpretador corrente. Note que help(modules) (note a ausência de aspas) resultará em um NameError (a menos que você tenha a má sorte de ter uma variável chamada módulos em seu ambiente de nomes, caso em que você obterá ajuda a respeito dessa variável).

  • help('algum_modulo'), onde algum_modulo é um módulo que ainda não foi importado (e ainda não é um objeto), lhe dará as informações de ajuda desse módulo.

  • help('alguma_keyword'): por exemplo ‘and’, ‘if’ ou ‘print’, isto é, help('and'), help('if') e help('print'). Estas são palavras-chave especiais reconhecidas em Python: elas não são objetos e, portanto, não podem ser passadas como argumentos para help. Passe o nome da palavra-chave como uma string para help funcionar, mas somente se você tiver a documentação em html instalada e se o interpretador Python tiver sido informado da localização da documentação ao se definir a variável de ambiente PYTHONDOCS.

4.5. Docstrings (strings de documentação)

O comando help(<object>) acessa as strings de documentação de objetos.

Qualquer string literal aparecendo como o primeiro item na definição de uma classe, função, método ou módulo, é considerada como sua docstring.

help inclui a docstring na informação que ela exibe sobre o objeto. Além da docstring, ela pode exibir algumas outras informações. Por exemplo, no caso de funções, ela exibe a assinatura da função. A docstring é armazenada no atributo __doc__ do objeto.

help(math.sin) 
# Help on built-in function sin in module math (<-- texto da docstring)
Help on built-in function sin in module math:

sin(...)
    sin(x)
    
    Return the sine of x (measured in radians).
print(math.sin.__doc__)
sin(x)

Return the sine of x (measured in radians).

Para funções, classes tipos, módulos, etc. definidos pelo usuário, deve-se sempre fornecer uma docstring.

Documentando uma função definida pelo usuário:

def power2and3(x):
    """Retorna a tupla (x**2, x**3)"""
    return x**2 ,x**3

power2and3(2)
(4, 8)
power2and3(4.5)
(20.25, 91.125)
power2and3(0+1j)
((-1+0j), (-0-1j))
help(power2and3)
Help on function power2and3 in module __main__:

power2and3(x)
    Retorna a tupla (x**2, x**3)
print(power2and3.__doc__)
Retorna a tupla (x**2, x**3)