# -*- coding: iso88591 -*-
# Aula 1 Instrospeção
#
# Observações iniciais: O curso inteiro será baseado em Python.
# eventualmente pode haver comentários sobre Java, mas não sou nenhum
# especialista nas características reflexivas dessa linguagem,
# principalmente suas versão mais nova.
#
# Usaremos Python 2.3 nesse curso.
#
# Referências:
# http://www-106.ibm.com/developerworks/library/l-pyint.html
# http://diveintopython.org/power_of_introspection/
#
# O que é introspecção: O programa olhando para as suas próprias
# estruturas, descobrindo, em tempo de execução, o seu estado.
#
# Mais formalmente dizemos que introspecção computacional é a capacidade
# de um programa examinar seus objetos e descobrir suas características
# como o que ele é (seu tipo ou classe), o que ele sabe (seu estado, ou
# variáveis membro) e o que ele sabe fazer (a quais métodos ele responde,
# que interfaces implementa).
#
# Esse tipo de capacidade é muito comum em linguagens orientadas a
# objetos. Java é um bom exemplo. Mesmo C++ possui alguma capacidade
# reflexiva.
#
# Vamos ver como instrospecção está presente em Python. Outro objetivo dessa
# primeira aula *recordar* a linguagem. Vou assumir que todos já programaram
# em Python na vida.
#
# 1) Uso do help no interpretador
#
help
help()
# Podemos então brincar um pouco com a ajuda iterativa e descobrir mais
# sobre a linguagem. Por exemplo, podemos descobrir a lista de palavras
# chave da linguagem ou quais modulos estão disponíveis.
#
# >>> keywords
#
# >>> modules
#
# >>> quit
#
# O que ocorre quando pedimos o help de um módulo?
#
help('meu_modulo')
# Olhando o código da do módulo, é fácil imaginar de onde são tiradas
# as informações. Mas como isso é possível?
#
# É claro que se poderia fazer um programa para ler o arquivo e gerar
# a ajuda. Mas em Python essas capacidades estão embutidas, basta usá-las.
# Vamos ver um pouco mais sobre isso.
#
# Vamos começar vendo um pouco o módulo sys, que nos dá informação sobre o
# ambiente de execução.
import sys
print sys.executable
print sys.platform
print sys.version
print sys.maxint
# Observação para o instrutor: Crie um programa bobo que imprime os
# parâmetros e chame-o.
print sys.argv
print sys.path
# Observação para instrutor: Esse talvez fosse mais interessante de ser chamado
# de um interpretador em shell que possui menos módulos carregados
print sys.modules
# Uma outra função pré-definida, muito útil, é a função dir. Ela permite
# descobrir todos os atributos de um objeto, como suas variáveis membro,
# os métodos implementados, etc.
print dir()
print dir(sys)
print dir('')
# O que ocorre se aplicarmos dir a um mpódulo?
print dir('__buildins__')
# Obs: o módulo builtins é um caso gozado. Ele não possui fonte. Na
# veradade ele é gerado pelo shell no início da execução.
# Outros exemplos legais:
print dir(42)
print dir([])
print dir(())
print dir({})
print dir(dir)
# Agora alguns exemplos com a nossa classe
from meu_modulo import *
pedro = Pessoa('Pedro')
cris = Pessoa('Cristina')
cris.outroDado = 23
print dir(pedro)
print dir(cris)
pedro.saudacao()
print dir(pedro.saudacao)
# Um atributo que muitos objetos possuem (em particular: módulos, classes,
# funções e métodos) é o __doc__. Ele deve conter uma string descrevendo
# o objeto (ele é sua documentação). Agora começa a aparecer como o sistema
# de ajudas do python funciona. Vamos ver a cadeia doc do módulo
# __builtins__
print __builtins__.__doc__
# Vamos continuar pelo nossos objetos.
print Pessoa.__doc__
print Pessoa.saudacao.__doc__
# E agora a docstring da função embutida dir
print dir.__doc__
# Agora passemos a instrospecção propriamente dita.
# Como vimos em Python tudo são objectos, mesmo as classes e os módulos,
# bem como as instâncias de classe. Portanto uma API uificada de introspecção
# pode ser usada. Algumas pergutas que podemos querer fazer a um objeto são:
# Qual o seu nome?
# Qual o seu tipo (que tipo de objeto é você)?
# Qual a sua identidade (RG)?
# Quais os seus dados (o que você sabe ou conhece)? Qual o seu estado?
# O que você pode fazer (quais os métodos que você responde)?
# Quam são seus pais (de quais classes essa classe deriva)?
# Vamos lidar com cada uma dessas perguntas.
# Qual o seu nome?
# Os objetos que possuem nome têm também um atributo __name__ que o guarda.
# Vejamos uns exemplos:
print dir()
directory = dir
print directory()
print directory.__name__
# Um valor curioso usado para identificar módulos rodando como
# programa principal.
print __name__
# Qual o seu tipo?
# A função pré-definida type devolve um objeto que representa o
# tipo de seu argumento. Esses objetos podem ser comparados entre
# si para verificar se dois objetos são do mesmo tipo. O módulo
# types possui os objetos que representam os tipos pré-definidos.
import types
print types.__doc__
dir(types)
s = 'uma cadeia de caracteres'
print type(s)
if type(s) is types.StringType: print 's é uma cadeia de caracteres'
print type(42)
print type([])
print type({})
print type(dir)
# Qual o seu RG? Qual a sua identidade?
# Para se obter um número que presenta unicamente cada objeto do sistema
# podemos usar a função pré-definida id.
print id.__doc__
# Vejamos um exemplo interessante.
listaA = [1, 2, 3]
listaB = [1, 2, 3]
listaC = listaB
print listaC
print listaB
print listaA
print id(listaA)
print id(listaB)
print id(listaC)
print listaA is listaB
print listaB is listaC
listaC.append(4)
print listaC
print listaB
print listaA
# Quais os seus dados? Como descobrir os atributos de um objeto.
# Já vimos a função dir que é capaz de listar todos os atributos
# de um objeto. Porém algumas vezes estamos interessados somente em
# verificar se um dado atributo existe e nesse caso manipulá-lo.
# Para isso podemos usar as funções hasattr e getattr
print hasattr.__doc__
print getattr.__doc__
print hasattr(id, '__doc__')
print getattr(id, '__doc__')
# Uma pergunta: como diferenciar métodos de dados? Basta usar a função
# pré-definida callable.
print callable.__doc__
print callable('a string')
print callable(dir)
# Podemos também testar se um objeto é de um certo tipo:
print isinstance.__doc__
print isinstance('uma cadeia', str)
print isinstance('uma cadeira', int)
print isinstance(1.0, float)
print isinstance(1.0, int)
# Verificar se é uma subclasse também dá.
print issubclass.__doc__
class SuperHeroi(Pessoa):
def saudacao(self):
'''Mostra educação.
'''
print 'Olá, sou o super', self.nome, '. Como você se chama?'
print issubclass(SuperHeroi, Pessoa)
print issubclass(Pessoa, SuperHeroi)
print issubclass(SuperHeroi, object)
# Finalmente, colocamos tudo junto na função interroga do módulo
# instroscpeccao. Vamos olhar o seu código e usá-la um pouco.
from introspeccao import *
interroga('string')
interroga(34)
interroga(Pessoa)
interroga(interroga)
syntax highlighted by Code2HTML, v. 0.9.1