sábado, 5 de dezembro de 2020

Alterando membros de classe em Python

Já sabemos que Python não tem palavra-chave static. Todas as variáveis que recebem um valor na declaração de classe são variáveis de classe.

Devemos ter cuidado ao alterar o valor da variável de uma classe. Se tentarmos mudar a variável de uma classe usando objeto, uma nova variável da instância (ou não estática) para aquele objeto particular é criada e esta variável obscurece as variáveis da classe. Abaixo está o programa Python para demonstrar o mesmo.

# Programa para testar a funcionalidade

# Classe para estudantes de ciência da computação 
class CSStudent:
    stream = 'cse' # Variável da classe
    def __init__(self, name, roll):
        self.name = name
        self.roll = roll

# Criação de objetos da classe CSStudent
a = CSStudent("Geek", 1)
b = CSStudent("Nerd", 2)

print ("Inicialmente")
print ("a.stream =", a.stream)
print ("b.stream =", b.stream)

# Isso não muda a variável da classe
# Em vez disso, cria uma variável de instância para o objeto
# 'a' que sombreia o membro da classe.
a.stream = "ece"

print ("\nDepois de mudar a.stream")
print ("a.stream =", a.stream)
print ("b.stream =", b.stream)

Resultado:

Initially
Inicialmente
a.stream = cse
b.stream = cse

Depois de mudar a.stream
a.stream = ece
b.stream = cse

Devemos alterar as variáveis da classe usando apenas o nome da classe.

# Programa para mostrar como fazer alterações na
# variável da classe em Python

# Classe para estudante de ciência da computação
class CSStudent:
    stream = 'cse' # Variável da classe  
    def __init__(self, name, roll):
        self.name = name
        self.roll = roll

# Novo objeto para implementação posterior
a = CSStudent("check", 3)
print("a.tream =", a.stream)

# Maneira correta de alterar o valor da variável de classe
CSStudent.stream = "mec"
print("\nA variável da classe mudou para mec")

# Novo objeto para implementação posterior
b = CSStudent("carter", 4)

print("\nValor da variável steam para cada objeto")
print("a.stream =", a.stream)
print("b.stream =", b.stream)

Resultado:

a.tream = cse

A variável da classe mudou para mec

Valor da variável steam para cada objeto
a.stream = mec
b.stream = mec

Artigo escrito por Nikhil Kumar Singh e traduzido por Acervo Lima de Changing Class Members in Python

Operadores lógicos com string em Python

Para strings em python, os operadores booleanos (and, or, not) funcionam. Vamos considerar as duas strings, a saber, str1 e str2 e tentar operadores booleanos nelas:

str1 = ''
str2 = 'Lima'

# repr é usado para imprimir a string junto com as aspas

# Retorna str1 
print(repr(str1 and str2))

# Retorna str1
print(repr(str2 and str1))

# Retorna str2
print(repr(str1 or str2))

# Retorna str2
print(repr(str2 or str1))

str1 = 'Acervo'

# Retorna str2
print(repr(str1 and str2))

# Retorna str1
print(repr(str2 and str1))

# Retorna str1
print(repr(str1 or str2))

# Retorna str2
print(repr(str2 or str1))

str1='coleção'

# Retorna False
print(repr(not str1))

str1 = ''

# Retorna True
print(repr(not str1))

Resultado:

''
''
'Lima'
'Lima'
'Lima'
'Acervo'
'Acervo'
'Lima'
False
True

A saída das operações booleanas entre as strings depende do seguinte:

  1. Python considera strings vazias como tendo valor booleano de ‘false’ e string não vazia como tendo valor booleano de ‘true’.
  2. Para o operador 'and', se o valor esquerdo for verdadeiro, o valor direito será verificado e retornado. Se o valor da esquerda for falso, ele será retornado.
  3. Para o operador 'or', se o valor esquerdo for verdadeiro, ele será retornado; caso contrário, se o valor esquerdo for falso, o valor direito será retornado.

Observe que os operadores bit a bit (|, &) não funcionam para strings.

Artigo escrito por Nikhil Kumar Singh e melhorado por Suchendra Adiga e traduzido por Acervo Lima de Logical Operators on String in Python

Classe String Template em Python

No módulo string, a classe Template nos permite criar sintaxe simplificada para especificação de saída. O formato usa nomes de placeholder formados por $ com identificadores Python válidos (caracteres alfanuméricos e sublinhados). Rodear o placeholder com colchetes permite que ele seja seguido por mais letras alfanuméricas sem espaços intermediários. Escrever $$ cria um único $ com escape.

String Template python

O modelo de string do Python é criado passando a string do modelo para seu construtor. Ele suporta substituições baseadas em $. Esta classe possui 2 métodos principais:

  • substitute(mapping, **kwds): Este método realiza substituições usando um dicionário com um processo semelhante a objetos de mapeamento baseados em chave. argumentos de palavra-chave também podem ser usados para o mesmo propósito. Caso o mapeamento baseado em chave e os argumentos de palavra-chave tenham a mesma chave, ele lança um TypeError. Se as chaves estiverem faltando, ele retornará um KeyError.
  • substitute(mapping, **kwds): o comportamento deste método é semelhante ao do método substitute, mas não lança um KeyError se uma chave estiver faltando, em vez disso, ele retorna um marcador de posição na string de resultado.

O método substitute() gera um KeyError quando um espaço reservado não é fornecido em um dicionário ou em um argumento de palavra-chave. Para aplicativos de estilo mala direta, os dados fornecidos pelo usuário podem estar incompletos e o método safe_substitute() pode ser mais apropriado - ele deixará os marcadores de posição inalterados se houver dados ausentes:

Abaixo estão alguns exemplos simples.

Exemplo 1:

# Um exemplo simples usando Template
from string import Template

# Cria um modelo que tenha espaço reservado para o valor de x
t = Template('x é $x')

# Valor substituto de x no modelo acima
print(t.substitute({'x' : 1}))

Resultado:

x é 1

A seguir está outro exemplo em que importamos nomes e marcas de alunos de uma lista e os imprimimos usando um modelo.

Exemplo 2:

# Um programa Python para demonstrar o
# funcionamento de Template
from string import Template

# Lista Aluno armazena o nome e as notas de três alunos
Aluno = [('Ram',90), ('Ankit',78), ('Bob',92)]

# Estamos criando uma estrutura básica para
# imprimir o nome e as notas dos alunos.
t = Template('Olá $nome, você tem a nota $nota') 

for i in Aluno:
    print (t.substitute(nome = i[0], nota = i[1])) 

Resultado:

Olá Ram, você tem a nota 90
Olá Ankit, você tem a nota 78
Olá Bob, você tem a nota 92

O exemplo abaixo mostra a implementação do método safe_substitute().

Exemplo 3:

from string import Template

template = Template('$nome é o novo $função da $empresa')

string = template.safe_substitute(nome='Raju Kumar', empresa='TCE')
print(string)

Resultado:

Raju Kumar é o novo $função da TCE

Observe que não fornecemos ao marcador de posição $função quaisquer dados, mas isso não gerará um erro, em vez disso, retornará o marcador de posição como uma string, conforme discutido acima.

Imprimindo uma template String

O atributo “template” do objeto Template pode ser usado para retornar a string do template conforme mostrado abaixo:

Exemplo:

t = Template('Eu sou $nome e venho de $cidade')
print('Template String =', t.template)

Resultado:

Template String = Eu sou $nome e venho de $cidade

Sinal de escape $

O $$ pode ser usado para escapar de $ e ser tratado como parte da string.

Exemplo:

template = Template('$$ é o simbolo usado para se referir ao $name')
string = template.substitute(name='Dollar')
print(string)

Resultado:

$ é o simbolo usado para se referir ao Dollar

O ${identificador}

O ${identificador} funciona de forma semelhante ao de $identificador. É útil quando caracteres identificadores válidos seguem o espaço reservado, mas não fazem parte do espaço reservado.

Exemplo:

template = Template('That $noun looks ${noun}y')
string = template.substitute(noun='Fish')
print(string)

Resultado:

That Fish looks Fishy

Outra aplicação para template é separar a lógica do programa dos detalhes de vários formatos de saída. Isso torna possível substituir modelos personalizados por arquivos XML, relatórios de texto simples e relatórios da web em HTML.

Observe que existem outras maneiras de imprimir a saída formatada como %d para inteiro, %f para flutuante.

Referência: https://docs.python.org/3.3/tutorial/stdlib2.html

Artigo escrito por Siddharth Lalwani e traduzido por Acervo Lima de String Template Class in Python

str() vs repr() em Python

str() e repr() são usados para obter uma representação de string do objeto.

Exemplo de str():

s = 'Olá, Acervo Lima'
print(str(s)) 
print(str(2.0/11.0)) 

Saída:

Olá, Acervo Lima
0.181818181818

Exemplo de repr():

s = 'Olá, Acervo Lima'
print(repr(s))
print(repr(2.0/11.0))

Saída:

'Olá, Acervo Lima'
0.18181818181818182

A partir da saída acima, podemos ver se imprimimos string usando a função repr(), em seguida, ela imprime com um par de aspas e, se calcularmos um valor, obtemos um valor mais preciso do que a função str().

A seguir estão as diferenças:

  • str() é usado para criar saída para o usuário final, enquanto repr() é usado principalmente para depuração e desenvolvimento. o objetivo de repr é ser inequívoco e str’s deve ser legível. Por exemplo, se suspeitarmos que um float tem um pequeno erro de arredondamento, repr irá nos mostrar, enquanto str pode não.
  • repr() calcula a representação de string "oficial" de um objeto (uma representação que tem todas as informações sobre o objeto) e str() é usado para calcular a representação de string "informal" de um objeto (uma representação que é útil para imprimir o objeto).
  • A função print e a função interna str() usam __str__ para exibir a representação de string do objeto, enquanto a função interna repr() usa __repr__ para exibir o objeto.

Vamos entender isso por um exemplo:

import datetime
today = datetime.datetime.now()

# Imprime formato legível para objeto de data e hora
print(str(today))

# imprime o formato oficial do objeto data-hora
print(repr(today))

Resultado:

2020-12-05 19:05:20.173734
datetime.datetime(2020, 12, 5, 19, 5, 20, 173734)

str() exibe a data de hoje de uma forma que o usuário pode entender a data e hora.

repr() imprime a representação “oficial” de um objeto de data e hora (significa que usando a representação de string “oficial” podemos reconstruir o objeto).

Como fazê-los funcionar para nossas próprias classes definidas?
Uma classe definida pelo usuário também deve ter um __repr__ se precisarmos de informações detalhadas para depuração. E se acharmos que seria útil ter uma versão string para os usuários, criamos uma função __str__.

# Programa Python para demonstrar a escrita
# de __repr__ e __str__ para classes definidas pelo usuário

# Uma classe definida pelo usuário para representar números complexos
class Complex:

    # construtor
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # Para chamar repr (). Imprime informações do objeto
    def __repr__(self):
        return 'Racional(%s, %s)' % (self.real, self.imag)

    # Para chamar str(). Imprime forma legível
    def __str__(self):
        return '%s + i%s' % (self.real, self.imag)

t = Complex(10, 20)

print(str(t))
print(repr(t))

Resultado:

10 + i20
Racional(10, 20)

Artigo escrito por Arpit Agarwal e melhorado por rajivsarkar67 e traduzido por Acervo Lima de str() vs repr() in Python

Como inserir vários valores do usuário em uma linha em Python?

Por exemplo, em C podemos fazer algo assim:

// lê dois valores em uma linha
scanf("%d %d", &x, &y)

Uma solução é usar input() duas vezes.

x, y = input(), input()

Outra solução é usar split().

x, y = input().split()

Observe que não temos que especificar explicitamente split('') porque split() usa qualquer caractere de espaço em branco como delimitador como padrão.

Uma coisa a se notar no código Python acima é que tanto x quanto y seriam do tipo string. Podemos convertê-los para inteiros usando outra linha.

x, y = [int(x), int(y)]

# Também podemos usar a compreensão de lista
x, y = [int(x) for x in [x, y]]

Abaixo está o código completo de uma linha para ler duas variáveis inteiras da entrada padrão usando divisão e compreensão de lista.

# Lê dois números a partir da entrada e os converte para int usando
# compreensão da lista
x, y = [int(x) for x in input().split()]
# Lê dois números a partir da entrada e os converte para int usando
# a função map
x, y = map(int, input().split())

Artigo escrito por Abhishek Shukla e melhorado por dev_aditya e traduzido por Acervo Lima de How to input multiple values from user in one line in Python?

Tratamento de exceções Python

O erro em Python pode ser de dois tipos, ou seja, erros de sintaxe e exceções. Erros são os problemas em um programa devido aos quais o programa interromperá a execução. Por outro lado, exceções são levantadas quando ocorrem alguns eventos internos que alteram o fluxo normal do programa.

A diferença entre erro de sintaxe e exceções

Erro de sintaxe: como o nome sugere, esse erro é causado por sintaxe incorreta no código. Isso leva ao encerramento do programa.

Exemplo

# inicializar a variável de quantidade
montante = 10000

# verifique se você está qualificado para
# Comprar Dsa no seu próprio ritmo ou não
if (montante > 2999)
    print("Você está qualificado para comprar Dsa no seu próprio ritmo")

Resultado:

  File "/home/thor/Documentos/teste.py", line 6
    if (montante > 2999)
                       ^
SyntaxError: invalid syntax

Exceções: as exceções são levantadas quando o programa está sintaticamente correto, mas o código resultou em um erro. Este erro não interrompe a execução do programa, porém altera o fluxo normal do programa.

Exemplo:

# inicializa a variável
marks = 10000

# tenta fazer uma divisão por zero
a = marks / 0
print(a)

Resultado:

Traceback (most recent call last):
  File "/home/thor/Documentos/teste.py", line 5, in 
    a = marks / 0
ZeroDivisionError: division by zero

No exemplo acima, levantou ZeroDivisionError, pois estamos tentando dividir um número por 0.

Nota: Exception é a classe base para todas as exceções em Python. Você pode verificar a hierarquia de exceções aqui.

try e except no tratamento de exceções

Vamos tentar acessar o elemento da matriz cujo índice está fora do limite e tratar a exceção correspondente.

# Programa python para mostrar como
# lidar com erros em tempo de execução

a = [1, 2, 3]
try:
    print("Segundo elemento = %d" %(a[1]))

    # Lança o erro IndexError porque
    # estamos tentando acessar um
    # elemento fora dos limites
    print("Quarto elemento = %d" %(a[3]))

except IndexError:
    print('O erro IndexError foi lançado')

Resultado:

Segundo elemento = 2
O erro IndexError foi lançado

Uma instrução try pode ter mais de uma cláusula except, para especificar manipuladores para diferentes exceções. Observe que no máximo um manipulador será executado.

# Programa para lidar com vários erros com uma instrução except
try :
    a = 3
    if a < 4 :

        # lança ZeroDivisionError para a = 3
        b = a / (a-3)

    # lança NameError se a >= 4
    print(f"Valor de b = {b}") 

# note que parenteses é necessário
# quando vamos lidar com mais de uma
# exceção
except(ZeroDivisionError, NameError): 
    print("Complicações surgirão, continuaram e foram superadas")

Resultado:

Complicações surgirão, continuaram e foram superadas

Se você alterar o valor de 'a' para maior ou igual a 4, a saída será:

Complicações surgirão, continuaram e foram superadas

A saída acima é assim porque assim que o python tenta acessar o valor de b, ocorre NameError.

Cláusula Else

Em python, você também pode usar a cláusula else no bloco try-except, que deve estar presente após todas as cláusulas except. O código entra no bloco else apenas se a cláusula try não gerar uma exceção.

# Programa para representar a cláusula else com try-except

# Função que retorna a / b 
def AbyB(a , b):
    try:
        c = ((a+b) / (a-b))
    except ZeroDivisionError:
        print("a/b resulta em 0")
    else:
        print(c)

AbyB(2.0, 3.0) 
AbyB(3.0, 3.0) 

A saída para o programa acima é:

-5.0
a/b resulta em 0

Palavra-chave finally em Python

Python fornece a palavra-chave finally, que sempre é executada após blocos try e except. O bloco finally sempre executa após o término normal do bloco try ou depois que o bloco try termina devido a alguma exceção.

Sintaxe:

try:
       # Algum código.... 

except:
       # bloco opcional
       # lidando com a exceção
else:
       # executa se não tiver nenhuma exceção

finally:
      # sempre é executado, com ou sem exceções

Exemplo:

# demonstração de finally

try:
    k = 5//0 # lança o erro de divisão por zero
    print(k)

# lida com o erro de divisão por zero
except ZeroDivisionError:
    print("Não é possivel dividir por zero")

finally:
    # Esse bloco sempre é executado
    # com ou sem exceções
    print('Isso é sempre executado')   

Resultado:

Não é possivel dividir por zero
Isso é sempre executado

Levantando exceções

A instrução raise permite que o programador force a ocorrência de uma exceção específica. O único argumento em aumento indica a exceção a ser levantada. Deve ser uma instância de Exception ou a classe exception (uma classe que deriva de Exception).

# Programa python demonstrando
# o uso de raise

try:
    raise NameError("Um erro!!!") # lança um erro
except NameError:
    print("Uma exceção")
    raise # Para determinar qual exceção ocorreu ou não 

A saída do código acima será simplesmente impressa na linha "Umerro", mas um erro de tempo de execução também ocorrerá na última devido a instrução raise na última linha. Portanto, a saída em sua linha de comando será semelhante a essa:

Uma exceção
Traceback (most recent call last):
  File "/home/thor/Documentos/teste.py", line 5, in 
    raise NameError("Um erro!!!") # lança um erro
NameError: Um erro!!!

Artigo escrito por Nikhil Kumar Singh (nickzuck_007) e melhorado por Akanksha_Rai, nikhilaggarwal3 e traduzido por Acervo Lima de Python Exception Handling

Qual é o valor máximo possível de um inteiro em Python?

Considere o programa Python abaixo.

# Um programa Python para demonstrar que podemos
# armazenar grandes números em Python

x = 10000000000000000000000000000000000000000000;
x = x + 1
print(x)

Resultado :

10000000000000000000000000000000000000000001

Em Python, o valor de um inteiro não é restrito pelo número de bits e pode se expandir até o limite da memória disponível (Fontes: esse e esse). Portanto, nunca precisamos de nenhum arranjo especial para armazenar grandes números (imagine fazer a aritmética acima em C/ C++).

Como uma observação lateral, no Python 3, há apenas um tipo “int” para todos os tipos de inteiros. Em Python 2.7. existem dois tipos separados "int" (que é de 32 bits) e "long int" que é o mesmo que "int" do Python 3.x, ou seja, pode armazenar números arbitrariamente grandes.

# Um programa Python para mostrar que existem dois tipos em
# Python 2.7: int e long int
# E em Python 3, há apenas um tipo: int

x = 10
print(type(x))

x = 10000000000000000000000000000000000000000000
print(type(x))

Saída em Python 2.7:

<type 'int'>
<type 'long'>

Saída em Python 3:

<type 'int'>
<type 'int'>

Podemos tentar programas mais interessantes, como abaixo:

# Imprimindo 100 elevado a 100
print(100**100)

Artigo escrito por Abhay Rathi e traduzido por Acervo Lima de What is the maximum possible value of an integer in Python ?