metaprogramação em python: decorators e metaclasses

51
metaprogramação em python: metaclass e decorators

Upload: felipe-volpone

Post on 14-Aug-2015

197 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Metaprogramação em Python: Decorators e Metaclasses

metaprogramação em python:

metaclass e decorators

Page 2: Metaprogramação em Python: Decorators e Metaclasses

@felipevolponegithub.com/felipevolpone

facebook.com/felipevolponelinkedin

Page 3: Metaprogramação em Python: Decorators e Metaclasses

por que

metaprogramação?

aprender

Page 4: Metaprogramação em Python: Decorators e Metaclasses
Page 5: Metaprogramação em Python: Decorators e Metaclasses

por que

é poderoso

reutilizar código

aumentar abstração

criar APIs mais ricas

Page 6: Metaprogramação em Python: Decorators e Metaclasses

decoratorshttps://www.python.org/dev/peps/pep-0318/

python 2.4

Page 7: Metaprogramação em Python: Decorators e Metaclasses

o que é!

!

@staticmethod  def  say_hello():          return  "Hello  TDC  :)"  !

#flask  @app.route('/')  def  hello_rest():                  return  "Hello  TDC  :)"  

Page 8: Metaprogramação em Python: Decorators e Metaclasses

como funciona

def  log(func):          def  internal():                  return  func()          return  internal  !

@log  def  say_hello():          return  "Hello  TDC"  

Page 9: Metaprogramação em Python: Decorators e Metaclasses

!

def  log(func):        …  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

Page 10: Metaprogramação em Python: Decorators e Metaclasses

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

Page 11: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

Page 12: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

Page 13: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

Page 14: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

Page 15: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)

}

Page 16: Metaprogramação em Python: Decorators e Metaclasses

print  say_hello  <function  say_hello  at  0x105909c80>  !

say_hello  =  log(say_hello)  print  say_hello  <function  internal  at  0x105909cf8>

Page 17: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

#@log  def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)  print  say_hello()

Page 18: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)  print  say_hello()  >  "Hello  TDC"

Page 19: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):          def  internal():                  return  func()          return  internal  !

def  say_hello():          return  "Hello  TDC"  !

say_hello  =  log(say_hello)  print  say_hello()  >  "Hello  TDC"

Page 20: Metaprogramação em Python: Decorators e Metaclasses
Page 21: Metaprogramação em Python: Decorators e Metaclasses

from  datetime  import  datetime  !def  log(func):          def  internal():                  now  =  datetime.now()  \                  .strftime(“%d/%m/%Y  %H:%M:%S")                  print  "Funcao  chamada:  %s  as  %s"  %                                                                (func.func_name,  now)                  return  func()                    return  internal  !print  say_hello()  >  "Funcao  chamada:  say_hello  as  17/07/2015  16:45:36"  >  "Hello  TDC"

Page 22: Metaprogramação em Python: Decorators e Metaclasses
Page 23: Metaprogramação em Python: Decorators e Metaclasses

def  log(func):       def  internal():         now  =  …                       print  "Funcao  chamada  ..."         return  func()               return  internal  !@log  def  say_hello(message):          return  message  @log  def  goodbye():          return  “goodbye"  !print  goodbye()  >  Funcao  chamada:  goodbye  as  17/07/2015  16:30:23  >  goodbye  print  say_hello("#python  no  TDC")  >  TypeError:  internal()  takes  no  arguments  (1  given)

Page 24: Metaprogramação em Python: Decorators e Metaclasses

!

def  log(func):       def  internal(*args,  **kwargs):         now  =  …         print  "Funcao  chamada:  …"           return  func(*args,  **kwargs)           return  internal

Page 25: Metaprogramação em Python: Decorators e Metaclasses

args é iterável kwargs é {}

Page 26: Metaprogramação em Python: Decorators e Metaclasses

def  example(func):          def  internal(*args,  **kwargs):                return  func(*args,  **kwargs)          return  internal  !

@example  def  sum_base(a,  b,  base=12):          return  a+b+base  !

print  sum_base(6,  10,  base=12)  >  28

Page 27: Metaprogramação em Python: Decorators e Metaclasses

combinando decorators

Page 28: Metaprogramação em Python: Decorators e Metaclasses

@timestamp  @log  def  say_message(msg):          return  msg  !

sum_func  =  timestamp(log(say_message))

Page 29: Metaprogramação em Python: Decorators e Metaclasses

[email protected]('/about')  def  about():          return  'The  about  page'  [email protected]('Failing  test')  def  test_example(self):          self.assertEquals(1,  2)  !

Page 30: Metaprogramação em Python: Decorators e Metaclasses

def  authentication(msg):  !        def  decorator(func):                  def  internal(*args,  **kwargs):                          user  =  get_session_user()                          if  user.valid:                                  return  func(*args,  **kwargs)                          else:                                  raise  Exception(msg)                  return  internal  !        return  decorator

Page 31: Metaprogramação em Python: Decorators e Metaclasses

@authentication("User  is  not  valid")  def  say_hello():          return  "Hello  TDC"  !say_hello  =  \  authentication(“User  is  not  valid")(say_hello)  !#quando  usuario  nao  eh  valido  print  say_hello()  >  raise  Exception(msg)  Exception:  User  is  not  valid

Page 32: Metaprogramação em Python: Decorators e Metaclasses

@json  @flask.get('/products/')  def  get_products():          return  {'products':  get_products()}  !@html  def  get_static_file(file_path):          return  open(file_path)  !@auth('admin')  def  delete_user():       pass  !@convert_object  @flask.post('/user/<id>')  def  get_user(model_user)          #  transforma  json  em  objeto  python          model_user.put()

Page 33: Metaprogramação em Python: Decorators e Metaclasses

cobre 90% dos casos

Page 34: Metaprogramação em Python: Decorators e Metaclasses

def  example(func):          def  internal(*args,  **kwargs):                  """Useless  decorator"""                  return  func(*args,  **kwargs)          return  internal  !@example  def  say_hello():          """A  simple  function  that  says  hello  TDC"""          return  "Hello  TDC"  !print  say_hello.func_name  print  say_hello.func_doc  >  "internal"  >  "Useless  decorator"  

Page 35: Metaprogramação em Python: Decorators e Metaclasses

def  example(func):          def  internal(*args,  **kwargs):                  "Useless  decorator"                  return  func(*args,  **kwargs)          internal.func_name  =  func.func_name          internal.func_doc  =  func.func_doc          return  internal  !@example  def  say_hello():          "Function  that  says  hello  TDC"          return  "Hello  TDC"  !print  say_hello.func_name,  say_hello.func_doc  >  “say_hello"  "Function  that  says  hello  TDC"

Page 36: Metaprogramação em Python: Decorators e Metaclasses

import wrapt

http://pyvideo.org/video/2617/advanced-methods-for-creat

Page 37: Metaprogramação em Python: Decorators e Metaclasses

metaclasses

Page 38: Metaprogramação em Python: Decorators e Metaclasses

class  User(object):   pass  !a  =  User()  type(a)  >  __main__.User  !type(User)  >  type  !type(str)  >  type  

Page 39: Metaprogramação em Python: Decorators e Metaclasses

isinstance(User,  type)  >  True  !isinstance(str,  type)  >  True

metaclass class

class

class

Page 40: Metaprogramação em Python: Decorators e Metaclasses

User object type

metaclass class

subclass instance

str instance type

user

object

instance

"tdc2015"instance

Page 41: Metaprogramação em Python: Decorators e Metaclasses

__init__

__new__

instância

user = User()metac

lass

clas

s

1

2

4

__call____init__

1.1 1.2

Page 42: Metaprogramação em Python: Decorators e Metaclasses

class  MyMetaclass(type):          pass  !class  Person(object):          __metaclass__  =  MyMetaclass  !print  type(Person)  >  <class  '__main__.  MyMetaclass'>  

Page 43: Metaprogramação em Python: Decorators e Metaclasses

exemplos

Page 44: Metaprogramação em Python: Decorators e Metaclasses

class  Person(object):          __metaclass__  =  LogMetaclass  !        def  say_hello(self):                  return  'hello  tdc'  

Page 45: Metaprogramação em Python: Decorators e Metaclasses

import  inspect,  wrap  !def  log_decorator(func):        @wrapt          def  inner(*args,  **kwargs):                  print  '[Logging]  %s  was  called'  %  (func.func_name,)                  return  func(*args,  **kwargs)          return  inner  !class  LogMetaclass(type):  !        def  __init__(cls,  *args,  **kwargs):                  for  prop  in  args[2]:  #propriedades  de  person                          method  =  getattr(cls,  prop)  !                        if  inspect.ismethod(method):                                  decorated_method  =  log_decorator(method)                                  setattr(cls,  prop,  decorated_method)  !                return  type.__init__(cls,  *args,  **kwargs)  

Page 46: Metaprogramação em Python: Decorators e Metaclasses

class  Person(object):          __metaclass__  =  LogMetaclass  !        def  say_hello(self):                  return  'hello  tdc'  !u  =  Person()  print  u.say_hello()  >  "[Logging]  say_hello  was  called"  >  “hello  tdc"  

Page 47: Metaprogramação em Python: Decorators e Metaclasses

import  inspect  !!class  ModelBasicProtocol(type):  !        def  __new__(cls,  name,  parents,  dct):  !                if  '__init__'  in  dct:                          init_function  =  dct['__init__']                          init_inspection  =  inspect.getargspec(init_function)  !                        if  init_inspection.defaults  is  None  and  len(init_inspection.args)  >  1:                                  raise  Exception(‘The  object  must  have  a  keywords  arguments  in  __init__')  !                return  type.__new__(cls,  name,  parents,  dct)  

Page 48: Metaprogramação em Python: Decorators e Metaclasses

class  TableProduct(object):          __metaclass__  =  ModelBasicProtocol  !        def  __init__(self,  name):                  pass  !e  =  TableProduct('Notebook')  >  Exception:  A  modelobject  must  have    a  keywords  arguments  in  __init__  

Page 49: Metaprogramação em Python: Decorators e Metaclasses

descriptors

https://speakerdeck.com/ramalho/python-encapsulation-with-descriptors-1

Page 50: Metaprogramação em Python: Decorators e Metaclasses

from  google.appengine.ext  import  ndb  !class  Event(ndb.Model):          name  =  ndb.StringProperty(required=True)          description  =  ndb.TextProperty(required=True)          logo  =  ndb.BlobKeyProperty(default=None)          date  =  ndb.DateTimeProperty()  

Page 51: Metaprogramação em Python: Decorators e Metaclasses

@felipevolpone