Dicas, truques e boas práticas para programadores Python - I
Johni Douglas Marangon
sobre mim
desenvolvedor de software desde de 2008
programador Python há cerca de 7 meses
contato
johnidouglas.com.br
github.com/johnidm
br.linkedin.com/in/johnidouglas
johni.douglas.marangon@gmail.com
objetivos
compartilhar o que estou aprendendo em Python
mostrar algumas coisas divertidas em Python
DUNDER
https://wiki.python.org/moin/DunderAlias
Dunder (Double UNDERscore)
__init__(self, *args, **kwargs)
__len__(self)
__repr__(self)
__add__(self, other)
Common dunders
OOP
Python não tem tipos primitivos
Tudo é objeto desde a versão 2.2
>>> type(7)
<class 'int'>
>>> dir(7)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__',
'__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__',
'__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__',
'__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__int__',
'__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__',
'__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__',
'__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__',
'__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__',
'__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__',
'__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__',
'__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator',
'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>> class PizzaTalk:
... pass
...
>>> type(PizzaTalk)
<class 'type'>
>>> dir(PizzaTalk)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__']
A maioria das pessoas aprende OOP com outras linguagens
Python tem peculiaridades - OOP Pythonica
class Parser:
""" private variable """
__count_iter = 0
def __init__(self, tokens):
""" Contructor method """
self.__tokens = tokens
def report(self):
""" Public method """
self.__build_report()
self._parser()
def __build_report(self):
""" Private method """
print(self.__count_iter)
def _parser(self):
""" Proteced method """
print(self.__tokens)
parser = Parser(['def', ':'])
parser.report()
tipagem dinamica mas não fraca
!= Java Script ou PHP
>>> 7 + "7"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Python não tem sobrecarga de métodos mas tem sobrecarga de operadores e passagem flexível de argumentos
class PizzaTalk:
id = 0
def __eq__(self, other):
return self.id == other.id
def __len__(self):
return 20
def __add__(self, other):
pass
p1 = PizzaTalk()
p1.id = 5
p2 = PizzaTalk()
p2.id = 6
p3 = p1 + p2
print(p1 == p2)
>>> False
print(len(p1))
>>> 20
some_func(fargs, *args, **kwargs)
Python não tem interface mas tem classes abstratas e herança multipla
https://www.python.org/dev/peps/pep-3119/
Mixin
class PizzaCalabresa:
def pagar(self):
print("Calabresa")
class PizzaStrogonoff:
def pagar(self):
print("Strogonoff")
class PizzaQuatroQueijos():
def pagar(self):
print("Quatro Queijos")
def pagamento(instance):
instance.pagar()
pagamento(PizzaCalabresa())
pagamento(PizzaStrogonoff())
pagamento(PizzaQuatroQueijos())
Propriedades
Getter e Setter é doença - use propriedades
As vezes uma variável pública já é o suficiente
class Token:
def __init__(self):
self.__name = 'unknown'
@property
def name(self):
return self.__name
@name.setter
def name(self, value):
if value != '':
raise BlankToken('Token.name')
self.__name = value
token = Token()
token.name = 'keyword'
print(token.name)
As vezes você pode usar uma função em um módulo.
Métodos estáticos
class Scanning:
@staticmethod
def print_token(token):
print(token)
@classmethod
def print_token_class(cls, token):
print(cls, token)
Scanning.print_token('number')
>>> number
Scanning.print_token_class('comment')
>>> <class '__main__.Scanning'> comment
Dicas
Inicializando listas e strings
my_list = [""] * 10
['', '', '', '', '', '', '', '', '', '']
my_string = 'O' * 10
OOOOOOOOOO
my_list = [1, 2, 3, 4]
>>> my_list[-1]
4
Índices negativos
Operadores ternários
is_pizza = 'true' if (event == "Pizza") else 'false'
fat = True
fitness = ("skinny", "fat")[fat]
print("Ali is ", fitness)
>>> Ali is fat
condition = True
number = 2 if condition else 1
number = (1, 2)[condition]
def difference(x, y):
return x - y
difference(5, 2)
3
difference(x=5, y=2)
3
difference(5, y=2)
3
difference(y=2, x=5)
3
Argumentos nomeados
def print_names(*args):
print(args)
print_names('John', 'Don', 'Bull')
>>> ('John', 'Don', 'Bull')
Keyword arguments
def report(**kwargs):
print(kwargs)
report(name="John", age=14, is_activated=True)
>>> {'is_activated': True, 'age': 14, 'name': 'John'}
def process(method, *middleware, **header):
print(method)
print(middleware)
print(header)
process("POST", "filter", "auth", agent="My Machine", time_out=100)
>>> POST
>>> ('filter', 'auth')
>>> {'time_out': 100, 'agent': 'My Machine'}
def get_type_token(self, token):
def is_integer():
return re.match("^[-+]?\d+$", token) is not None
def is_float():
return re.match("^[-+]?\d+\.\d+?$", token) is not None
if is_integer(token):
return 'integer'
elif is_float(token):
return 'float'
Closures Functions
Retorno múltiplo
def divide(x, y):
quotient = x/y
remainder = x % y
return quotient, remainder
q, r = divide(22, 7)
q, _ = divide(22, 7)
def getImageData(filename):
...
return size, (format, version, compression), (width,height)
size, type, dimensions = getImageData('python.png')
_, type, _ = getImageData('python.png')
format, version, compression = type
name, method, trace = 'called', 'call', True
Formatação de strings
https://docs.python.org/3/library/string.html#string-formatting
"How to write {} code that works".format("shit")
>>> 'How to write shit code that works'
"{0}, your code is {1} your argument is {1}".format("John", "shit")
>>> 'John, your code is shit your argument is shit'
"My code is {wtf}".format(wtf="beautiful")
>>> 'My code is beautiful'
class PizzaTech:
name = "Strogonoff"
pizza = PizzaTech()
"We go to eat a {0.name} pizza".format(pizza)
>>> 'We go to eat a Strogonoff pizza'
Docstring Conventions
def example_method(self, param1, param2):
"""Class methods are similar to regular functions.
Note:
Do not include the `self` parameter in the ``Args`` section.
Args:
param1: The first parameter.
param2: The second parameter.
Returns:
True if successful, False otherwise.
"""
print(example_method.__doc__)
python -i module.py
>>> help(example_method)
Desafio
http://hotsites.folha.com.br/2015/03/31/selecao/
Perguntas
Referências
https://www.youtube.com/watch?v=BwAF7ke7Px0&i
http://book.pythontips.com/en/latest/
http://python-notes.curiousefficiency.org/en/latest/python3/index.html
Dicas, truques e boas práticas para programadores Python - I
By Johni Douglas Marangon
Dicas, truques e boas práticas para programadores Python - I
Talk apresentada no 5o Pizza Talk
- 1,322