O GoConqr está de visual novo! Conte para nós o que você achou.

Flashcards

026_Classes_Part2

Serhii Yurskyi Python Advanced Inglês 46 flashcards

Flashcards do conjunto (46)

  1. 1038_003_Class Decoratorsdef decorator(cls): # On @ decoration
    class Wrapper:
    def __init__(self, *args): # On instance creation
    self.wrapped = cls(*args)
    def __getattr__(self, name): # On attribute fetch
    return getattr(self.wrapped, name)
    return Wrapper
    @decorator
    class C: # C = decorator(C)
    def __init__(self, x, y): # Run by Wrapper.__init__
    self.attr = 'spam'
    x = C(6, 7) # Really calls Wrapper(6, 7)
    print(x.attr) # Runs Wrapper.__getattr__, prints "spam"
  2. 2038_004_Supporting multiple instancesclass Decorator:
    def __init__(self, C): # On @ decoration
    self.C = C
    def __call__(self, *args): # On instance creation
    self.wrapped = self.C(*args)
    return self
    def __getattr__(self, attrname): # On atrribute fetch
    return getattr(self.wrapped, attrname)
    @Decorator
    class C: # C = Decorator(C)
    pass
    x = C()
    y = C() # Overwrites x!
    def decorator(C): # On @ decoration
    class Wrapper:
    def __init__(self, *args): # On instance creation
    self.wrapped = C(*args)
    return Wrapper
    class Wrapper:
    pass
    def decorator(C): # On @ decoration
    def onCall(*args): # On instance creation
    return Wrapper(C(*args)) # Embed instance in instance
    return onCall
  3. 3038_005_Decorator Nestingdef d1(F):
    return F
    def d2(F):
    return F
    def d3(F):
    return F
    #
    @d1
    @d2
    @d3
    def func(): # func = d1(d2(d3(func)))
    print('spam')
    #
    func() # Prints "spam"
    def d1(F): return lambda: 'X' + F()
    def d2(F): return lambda: 'Y' + F()
    def d3(F): return lambda: 'Z' + F()
    @d1
    @d2
    @d3
    def func(): # func = d1(d2(d3(func)))
    return 'spam'
    print(func()) # Prints "XYZspam"
  4. 4038_006_Decorator Argumentslook in the book
  5. 5038_007_Decorators Manage Functions and Classes, Toolook in the book
  6. 6038_008_Coding Function Decorators not to thee end### file: decorator1.py
    class tracer:
    def __init__(self, func): # On @ decoration: save original func
    self.calls = 0
    self.func = func
    def __call__(self, *args): # On later calls: run original func
    self.calls += 1
    print('call %s to %s' % (self.calls, self.func.__name__))
    self.func(*args)
    @tracer
    def spam(a, b, c): # spam = tracer(spam)
    print(a + b + c) # Wraps spam in a decorator object
    # from decorator1 import spam
    print('#' * 23 + ' Really calls the tracer wrapper object')
    spam(1, 2, 3) # Really calls the tracer wrapper object
    # call 1 to spam
    # 6
    #
    print('#' * 23 + ' Invokes __call__ in class')
    spam('a', 'b', 'c') # Invokes __call__ in class
    # call 2 to spam
    # abc
    #
    print('#' * 23 + ' Number calls in wrapper state information')
    print(spam.calls) # Number calls in wrapper state information
    # 2
    print(spam)
    #
    #
    calls = 0
    def tracer(func, *args):
    global calls
    calls += 1
    print('call %s to %s' % (calls, func.
  7. 7038_009_Class instance attributesclass tracer: # State via instance attributes
    def __init__(self, func): # On @ decorator
    self.calls = 0 # Save func for later call
    self.func = func
    def __call__(self, *args, **kwargs): # On call to original function
    self.calls += 1
    print('call %s to %s' % (self.calls, self.func.__name__))
    return self.func(*args, **kwargs)
    @tracer
    def spam(a, b, c): # Same as: spam = tracer(spam)
    print(a + b + c) # Triggers tracer.__init__
    @tracer
    def eggs(x, y): # Same as: eggs = tracer(eggs)
    print(x ** y) # Wraps eggs in a tracer object
    spam(1, 2, 3) # Really calls tracer instance: runs tracer.__call__
    spam(a=4, b=5, c=6) # spam is an instance attribute
    eggs(2, 16) # Really calls tracer instance, self.func is eggs
    eggs(4, y=4) # self.calls is per-function here (need 3.0 nonlocal)
  8. 8038_010_Enclosing scopes and globalscalls = 0
    def tracer(func): # State via enclosing scope and global
    def wrapper(*args, **kwargs): # Instead of class attributes
    global calls # calls is global, not per-function
    calls += 1
    print('call %s to %s' % (calls, func.__name__))
    return func(*args, **kwargs)
    return wrapper
    @tracer
    def spam(a, b, c): # Same as: spam = tracer(spam)
    print(a + b + c)
    @tracer
    def eggs(x, y): # Same as: eggs = tracer(eggs)
    print(x ** y)
    spam(1, 2, 3) # Really calls wrapper, bound to func
    spam(a=4, b=5, c=6) # wrapper calls spam
    eggs(2, 16) # Really calls wrapper, bound to eggs
    eggs(4, y=4) # Global calls is not per-function here!
  9. 9038_012_Function attributesdef tracer(func): # State via enclosing scope and func attr
    def wrapper(*args, **kwargs): # calls is per-function, not global
    wrapper.calls += 1
    print('call %s to %s' % (wrapper.calls, func.__name__))
    return func(*args, **kwargs)
    wrapper.calls = 0
    return wrapper
  10. 10038_013_Class Blunders I Decorating Class Methods not to the endclass tracer:
    def __init__(self, func): # On @ decorator
    self.calls = 0 # Save func for later call
    self.func = func
    def __call__(self, *args, **kwargs): # On call to original function
    self.calls += 1
    print('call %s to %s' % (self.calls, self.func.__name__))
    return self.func(*args, **kwargs)
    @tracer
    def spam(a, b, c): # spam = tracer(spam)
    print(a + b + c) # Triggers tracer.__init__
    spam(1, 2, 3) # Runs tracer.__call__
    spam(a=4, b=5, c=6) # spam is an instance attribute
    class Person:
    def __init__(self, name, pay):
    self.name = name
    self.pay = pay
    @tracer
    def giveRaise(self, percent): # giveRaise = tracer(giverRaise)
    self.pay *= (1.0 + percent)
    @tracer
    def lastName(self): # lastName = tracer(lastName)
    return self.name.split()[-1]
    bob = Person('Bob Smith', 50000) # tracer remembers method
  11. 11038_014_Using nested functions to decorate methods not to the end# A decorator for both functions and methods
    def tracer(func): # Use function, not class with __call__
    calls = 0 # Else "self" is decorator instance only!
    def onCall(*args, **kwargs):
    nonlocal calls
    calls += 1
    print('call %s to %s' % (calls, func.__name__))
    return func(*args, **kwargs)
    return onCall
    # Applies to simple functions
    @tracer
    def spam(a, b, c): # spam = tracer(spam)
    print(a + b + c) # onCall remembers spam
    spam(1, 2, 3) # Runs onCall(1, 2, 3)
    spam(a=4, b=5, c=6)
    # Applies to class method functions too!
    class Person:
    def __init__(self, name, pay):
    self.name = name
    self.pay = pay
    @tracer
    def giveRaise(self, percent): # giveRaise = tracer(giverRaise)
    self.pay *= (1.0 + percent) # onCall remembers giveRaise
    @tracer
    def lastName(self): # lastName = tracer(lastName)
    return self.name.split()[-1]
    print('methods...')
    bob = Pe
  12. 12038_015_Using descriptors to decorate methods not to the endclass Descriptor(object):
    def __get__(self, instance, owner): ...
    class Subject:
    attr = Descriptor()
    X = Subject()
    X.attr # Roughly runs Descriptor.__get__(Subject.attr, X, Subject)
    class tracer(object):
    def __init__(self, func): # On @ decorator
    self.calls = 0 # Save func for later call
    self.func = func
    def __call__(self, *args, **kwargs): # On call to original func
    self.calls += 1
    print('call %s to %s' % (self.calls, self.func.__name__))
    return self.func(*args, **kwargs)
    def __get__(self, instance, owner): # On method attribute fetch
    return wrapper(self, instance)
    class wrapper:
    def __init__(self, desc, subj): # Save both instances
    self.desc = desc # Route calls back to decr
    self.subj = subj
    def __call__(self, *args, **kwargs):
    return self.desc(self.subj, *args, **kwargs) # Runs tracer.__call__
    @tracer
    def spam(a, b, c): # spam = tracer(spam)
    ...same as prior...
  13. 13038_016_Timing Calls not to the endimport time
    class timer:
    def __init__(self, func):
    self.func = func
    self.alltime = 0
    def __call__(self, *args, **kargs):
    start = time.clock()
    result = self.func(*args, **kargs)
    elapsed = time.clock() - start
    self.alltime += elapsed
    print('%s: %.5f, %.5f' % (self.func.__name__, elapsed, self.alltime))
    return result
    @timer
    def listcomp(N):
    return [x * 2 for x in range(N)]
    @timer
    def mapcall(N):
    return map((lambda x: x * 2), range(N))
    result = listcomp(5) # Time for this call, all calls, return value
    listcomp(50000)
    listcomp(500000)
    listcomp(1000000)
    print(result)
    print('allTime = %s' % listcomp.alltime) # Total time for all listcomp calls
    print('')
    result = mapcall(5)
    mapcall(50000)
    mapcall(500000)
    mapcall(1000000)
    print(result)
    print('allTime = %s' % mapcall.alltime) # Total time for all mapcall calls
    print('map/comp = %s' % round(mapcall.alltime / listcomp.alltime, 3))
    ...
    import sys
    @timer
    def listcomp(N):
    return [x * 2 for x in range(N)]
    if sys.version_inf
  14. 14038_017_Adding Decorator Argumentstoo big
  15. 15038_018_Coding Class Decorators_Singleton Classestoo big
  16. 16038_019_Tracing Object Interfacestoo big
  17. 17038_020_Class Blunders II Retaining Multiple Instances not to the endclass Tracer:
    def __init__(self, aClass): # On @decorator
    self.aClass = aClass # Use instance attribute
    def __call__(self, *args): # On instance creation
    self.wrapped = self.aClass(*args) # ONE (LAST) INSTANCE PER CLASS!
    return self
    def __getattr__(self, attrname):
    print('Trace: ' + attrname)
    return getattr(self.wrapped, attrname)
    @Tracer # Triggers __init__
    class Spam: # Like: Spam = Tracer(Spam)
    def display(self):
    print('Spam!' * 8)
    ...
    food = Spam() # Triggers __call__
    food.display() # Triggers __getattr__
    @Tracer
    class Person: # Person = Tracer(Person)
    def __init__(self, name): # Wrapper bound to Person
    self.name = name
    bob = Person('Bob') # bob is really a Wrapper
    print(bob.name) # Wrapper embeds a Person
    Sue = P
  18. 18038_021_Decorators Versus Manager Functionsinstances = {}
    def getInstance(aClass, *args):
    if aClass not in instances:
    instances[aClass] = aClass(*args)
    return instances[aClass]
    bob = getInstance(Person, 'Bob', 40, 10) # Versus: bob = Person('Bob', 40, 10)
    instances = {}
    def getInstance(object):
    aClass = object.__class__
    if aClass not in instances:
    instances[aClass] = object
    return instances[aClass]
    bob = getInstance(Person('Bob', 40, 10)) # Versus: bob = Person('Bob', 40, 10)
    def func(x, y): # Nondecorator version
    ... # def tracer(func, args): ... func(*args)
    result = tracer(func, (1, 2)) # Special call syntax
    @tracer
    def func(x, y): # Decorator version
    ... # Rebinds name: func = tracer(func)
    result = func(1, 2) # Normal call syntax
  19. 19038_022_Managing Functions and Classes Directlytoo big
    look at the book
  20. 20038_023_Implementing Private Attributestoo big
  21. 21038_024_Generalizing for Public Declarations, Toolook at the book
  22. 22038_025_Caveat operator overloading methods fail to delegate under 3.0look at the book
  23. 23038_026_Implementation alternatives __getattribute__ inserts, call stack inspectionlook at the book
  24. 24038_027_Example Validating Function Arguments038_027_Example Validating Function Arguments
  25. 25038_028_Basic Range-Testing Decorator for Positional Argumentstoo big
  26. 26038_029_Generalizing for Keywords and Defaults, Tootoo big
  27. 27038_030_Implementation Detailslook at the book
  28. 28038_032_Decorator Arguments Versus Function Annotations not to the end@rangetest(a=(1, 5), c=(0.0, 1.0))
    def func(a, b, c): # func = rangetest(..)(func)
    print(a + b + c)
    @rangetest
    def func(a:(1, 5), b, c:(0.0, 1.0)):
    print(a + b + c)
    # Using decorator arguments
    def rangetest(**argchecks):
    def onDecorator(func):
    def onCall(*pargs, **kargs):
    print(argchecks)
    for check in argchecks: pass # Add validation code here
    return func(*pargs, **kargs)
    return onCall
    return onDecorator
    @rangetest(a=(1, 5), c=(0.0, 1.0))
    def func(a, b, c): # func = rangetest(..)(func)
    print(a + b + c)
    func(1, 2, c=3) # Runs onCall, argchecks in scope
    # Using function annotations
    def rangetest(func):
    def onCall(*pargs, **kargs):
    argchecks = func.__annotations__
    print(argchecks)
    for check in argchecks: pass # Add validation code here
    return func(*pargs, **kargs)
    return onCall
    @rangetest
    def func(a:(1, 5), b, c:(0.0, 1.0)): # func = rangetest(func)
    print(a + b
  29. 29039_002_Metaclasses Versus Class Decorators Round 1def extra(self, arg): ...
    def extras(Class):
    if required():
    Class.extra = extra
    return Class
    class Client1: ...
    Client1 = extras(Client1)
    class Client2: ...
    Client2 = extras(Client2)
    class Client3: ...
    Client3 = extras(Client3)
    X = Client1()
    X.extra()
    def extra(self, arg): ...
    def extras(Class):
    if required():
    Class.extra = extra
    return Class
    @extras
    class Client1: ... # Client1 = extras(Client1)
    @extras
    class Client2: ... # Rebinds class independent of instances
    @extras
    class Client3: ...
    X = Client1() # Makes instance of augmented class
    X.extra() # X is instance of original Client1
  30. 30039_003_Classes Are Instances of typelook at the book
  31. 31039_004_Class Statement Protocollook at the book
  32. 32039_005_Declaring Metaclasseslook at the book
  33. 33039_006_Coding Metaclassesclass Meta(type):
    def __new__(meta, classname, supers, classdict):
    # Run by inherited type.__call__
    return type.__new__(meta, classname, supers, classdict)
    class MetaOne(type):
    def __new__(meta, classname, supers, classdict):
    print('In MetaOne.new:', classname, supers, classdict, sep='\n...')
    return type.__new__(meta, classname, supers, classdict)
    class Eggs:
    pass
    print('making class')
    class Spam(Eggs, metaclass=MetaOne): # Inherits from Eggs, instance of Meta
    data = 1 # Class data attribute
    def meth(self, arg): # Class method attribute
    pass
    print('making instance')
    X = Spam()
    print('data:', X.data)
  34. 34039_007_Customizing Construction and Initializationclass MetaOne(type):
    def __new__(meta, classname, supers, classdict):
    print('In MetaOne.new: ', classname, supers, classdict, sep='\n...')
    return type.__new__(meta, classname, supers, classdict)
    def __init__(Class, classname, supers, classdict):
    print('In MetaOne init:', classname, supers, classdict, sep='\n...')
    print('...init class object:', list(Class.__dict__.keys()))
    class Eggs:
    pass
    print('making class')
    class Spam(Eggs, metaclass=MetaOne): # Inherits from Eggs, instance of Meta
    data = 1 # Class data attribute
    def meth(self, arg): # Class method attribute
    pass
    print('making instance')
    X = Spam()
    print('data:', X.data)
  35. 35039_008_Using simple factory functions# A simple function can serve as a metaclass too
    def MetaFunc(classname, supers, classdict):
    print('In MetaFunc: ', classname, supers, classdict, sep='\n...')
    return type(classname, supers, classdict)
    class Eggs:
    pass
    print('making class')
    class Spam(Eggs, metaclass=MetaFunc): # Run simple function at end
    data = 1 # Function returns class
    def meth(self, args):
    pass
    print('making instance')
    X = Spam()
    print('data:', X.data)
  36. 36039_009_Overloading class creation calls with metaclasses# __call__ can be redefined, metas can have metas
    class SuperMeta(type):
    def __call__(meta, classname, supers, classdict):
    print('In SuperMeta.call: ', classname, supers, classdict, sep='\n...')
    return type.__call__(meta, classname, supers, classdict)
    class SubMeta(type, metaclass=SuperMeta):
    def __new__(meta, classname, supers, classdict):
    print('In SubMeta.new: ', classname, supers, classdict, sep='\n...')
    return type.__new__(meta, classname, supers, classdict)
    def __init__(Class, classname, supers, classdict):
    print('In SubMeta init:', classname, supers, classdict, sep='\n...')
    print('...init class object:', list(Class.__dict__.keys()))
    class Eggs:
    pass
    print('making class')
    class Spam(Eggs, metaclass=SubMeta):
    data = 1
    def meth(self, arg):
    pass
    print('making instance')
    X = Spam()
    print('data:', X.data)
  37. 37039_010_Overloading class creation calls with normal classesclass SuperMeta:
    def __call__(self, classname, supers, classdict):
    print('In SuperMeta.call: ', classname, supers, classdict, sep='\n...')
    Class = self.__New__(classname, supers, classdict)
    self.__Init__(Class, classname, supers, classdict)
    return Class
    class SubMeta(SuperMeta):
    def __New__(self, classname, supers, classdict):
    print('In SubMeta.new: ', classname, supers, classdict, sep='\n...')
    return type(classname, supers, classdict)
    def __Init__(self, Class, classname, supers, classdict):
    print('In SubMeta init:', classname, supers, classdict, sep='\n...')
    print('...init class object:', list(Class.__dict__.keys()))
    class Eggs:
    pass
    print('making class')
    class Spam(Eggs, metaclass=SubMeta()): # Meta is normal class instance
    data = 1 # Called at end of statement
    def meth(self, arg):
    pass
    print('making instance')
    X = Spam()
    print('data:', X.data)
  38. 38039_011_Instances Versus Inheritanceclass MetaOne(type):
    def __new__(meta, classname, supers, classdict): # Redefine type method
    print('In MetaOne.new:', classname)
    return type.__new__(meta, classname, supers, classdict)
    def toast(self):
    print('toast')
    class Super(metaclass=MetaOne): # Metaclass inherited by subs too
    def spam(self): # MetaOne run twice for two classes
    print('spam')
    class C(Super): # Superclass: inheritance versus instance
    def eggs(self): # Classes inherit from superclasses
    print('eggs') # But not from metclasses
    X = C()
    X.eggs() # Inherited from C
    X.spam() # Inherited from Super
    X.toast() # Not inherited from metaclass
  39. 39039_012_Manual Augmentation# Extend manually - adding new methods to classes
    class Client1:
    def __init__(self, value):
    self.value = value
    def spam(self):
    return self.value * 2
    class Client2:
    value = 'ni?'
    def eggsfunc(obj):
    return obj.value * 4
    def hamfunc(obj, value):
    return value + 'ham'
    Client1.eggs = eggsfunc
    Client1.ham = hamfunc
    Client2.eggs = eggsfunc
    Client2.ham = hamfunc
    X = Client1('Ni!')
    print(X.spam())
    print(X.eggs())
    print(X.ham('bacon'))
    Y = Client2()
    print(Y.eggs())
    print(Y.ham('bacon'))
  40. 40039_013_Metaclass-Based Augmentation not to the end# Extend with a metaclass - supports future changes better
    def eggsfunc(obj):
    return obj.value * 4
    def hamfunc(obj, value):
    return value + 'ham'
    class Extender(type):
    def __new__(meta, classname, supers, classdict):
    classdict['eggs'] = eggsfunc
    classdict['ham'] = hamfunc
    return type.__new__(meta, classname, supers, classdict)
    class Client1(metaclass=Extender):
    def __init__(self, value):
    self.value = value
    def spam(self):
    return self.value * 2
    class Client2(metaclass=Extender):
    value = 'ni?'
    X = Client1('Ni!')
    print(X.spam())
    print(X.eggs())
    print(X.ham('bacon'))
    Y = Client2()
    print(Y.eggs())
    print(Y.ham('bacon'))
    # Can also configure class based on runtime tests
    class MetaExtend(type):
    def __new__(meta, classname, supers, classdict):
    if sometest():
    classdict['eggs'] = eggsfunc1
    else:
    classdict['eggs'] = eggsfunc2
    if someothertest():
    classdict['ham'] = hamfunc
    else:
    classdict['ham'] = lambda *args: 'Not supported'
    ret
  41. 41039_014_Metaclasses Versus Class Decorators Round 2# Extend with a decorator: same as providing __init__ in a metaclass
    def eggsfunc(obj):
    return obj.value * 4
    def hamfunc(obj, value):
    return value + 'ham'
    def Extender(aClass):
    aClass.eggs = eggsfunc # Manages class, not instance
    aClass.ham = hamfunc # Equiv to metaclass __init__
    return aClass
    @Extender
    class Client1: # Client1 = Extender(Client1)
    def __init__(self, value): # Rebound at end of class stmt
    self.value = value
    def spam(self):
    return self.value * 2
    @Extender
    class Client2:
    value = 'ni?'
    X = Client1('Ni!') # X is a Client1 instance
    print(X.spam())
    print(X.eggs())
    print(X.ham('bacon'))
    Y = Client2()
    print(Y.eggs())
    print(Y.ham('bacon'))
  42. 42039_015_Managing instances instead of classes# Class decorator to trace external instance attribute fetches
    def Tracer(aClass): # On @decorator
    class Wrapper:
    def __init__(self, *args, **kargs): # On instance creation
    self.wrapped = aClass(*args, **kargs) # Use enclosing scope name
    def __getattr__(self, attrname):
    print('Trace:', attrname) # Catches all but .wrapped
    return getattr(self.wrapped, attrname) # Delegate to wrapped object
    return Wrapper
    @Tracer
    class Person: # Person = Tracer(Person)
    def __init__(self, name, hours, rate): # Wrapper remembers Person
    self.name = name
    self.hours = hours
    self.rate = rate # In-method fetch not traced
    def pay(self):
    return self.hours * self.rate
    bob = Person('Bob', 40, 50) # bob is really a Wrapper
    print(bob.name) # Wrapper embeds a Person
    print(bob.pay())
  43. 43039_016_Tracing with Decoration Manually not to the end, too big### File: mytools.py
    # File mytools.py: assorted decorator tools
    def tracer(func): # Use function, not class with __call__
    calls = 0 # Else self is decorator instance only
    def onCall(*args, **kwargs):
    nonlocal calls
    calls += 1
    print('call %s to %s' % (calls, func.__name__))
    return func(*args, **kwargs)
    return onCall
    import time
    def timer(label='', trace=True): # On decorator args: retain args
    def onDecorator(func): # On @: retain decorated func
    def onCall(*args, **kargs): # On calls: call original
    start = time.clock() # State is scopes + func attr
    result = func(*args, **kargs)
    elapsed = time.clock() - start
    onCall.alltime += elapsed
    if trace:
    format = '%s%s: %.5f, %.5f'
    values = (label, func.__name__, elapsed, onCall.alltime)
    print(format % values)
    return result
    onCall.alltime = 0
  44. 44039_017_Tracing with Metaclasses and Decorators# Metaclass that adds tracing decorator to every method of a client class
    from types import FunctionType
    from mytools import tracer
    class MetaTrace(type):
    def __new__(meta, classname, supers, classdict):
    for attr, attrval in classdict.items():
    if type(attrval) is FunctionType: # Method?
    classdict[attr] = tracer(attrval) # Decorate it
    return type.__new__(meta, classname, supers, classdict) # Make class
    class Person(metaclass=MetaTrace):
    def __init__(self, name, pay):
    self.name = name
    self.pay = pay
    def giveRaise(self, percent):
    self.pay *= (1.0 + percent)
    def lastName(self):
    return self.name.split()[-1]
    bob = Person('Bob Smith', 50000)
    sue = Person('Sue Jones', 100000)
    print(bob.name, sue.name)
    sue.giveRaise(.10)
    print(sue.pay)
    print(bob.lastName(), sue.lastName())
  45. 45039_018_Applying Any Decorator to Methods not to the end# Metaclass factory: apply any decorator to all methods of a class
    from types import FunctionType
    from mytools import tracer, timer
    def decorateAll(decorator):
    class MetaDecorate(type):
    def __new__(meta, classname, supers, classdict):
    for attr, attrval in classdict.items():
    if type(attrval) is FunctionType:
    classdict[attr] = decorator(attrval)
    return type.__new__(meta, classname, supers, classdict)
    return MetaDecorate
    class Person(metaclass=decorateAll(tracer)): # Apply a decorator to all
    def __init__(self, name, pay):
    self.name = name
    self.pay = pay
    def giveRaise(self, percent):
    self.pay *= (1.0 + percent)
    def lastName(self):
    return self.name.split()[-1]
    bob = Person('Bob Smith', 50000)
    sue = Person('Sue Jones', 100000)
    print(bob.name, sue.name)
    sue.giveRaise(.10)
    print(sue.pay)
    print(bob.lastName(), sue.lastName())
    class Person(metaclass=decorateAll(tracer)): # Apply tracer
    class Person(metaclass=decorateAll(timer())): #
  46. 46039_019_Metaclasses Versus Class Decorators Round 3 not to the end# Class decorator factory: apply any decorator to all methods of a class
    from types import FunctionType
    from mytools import tracer, timer
    def decorateAll(decorator):
    def DecoDecorate(aClass):
    for attr, attrval in aClass.__dict__.items():
    if type(attrval) is FunctionType:
    setattr(aClass, attr, decorator(attrval)) # Not __dict__
    return aClass
    return DecoDecorate
    @decorateAll(tracer) # Use a class decorator
    class Person: # Applies func decorator to methods
    def __init__(self, name, pay): # Person = decorateAll(..)(Person)
    self.name = name # Person = DecoDecorate(Person)
    self.pay = pay
    def giveRaise(self, percent):
    self.pay *= (1.0 + percent)
    def lastName(self):
    return self.name.split()[-1]
    bob = Person('Bob Smith', 50000)
    sue = Person('Sue Jones', 100000)
    print(bob.name, sue.name)
    sue.giveRaise(.10)
    print(sue.pay)
    print(bob.lastName(), sue.lastName())
    @decorateAll(tracer)

Informações

Descrição
Advanced Python FlashCards sobre 026_Classes_Part2, criado por Serhii Yurskyi em 22-09-2019.
Criado por
Serhii Yurskyi
Visualizações
0
Avaliação

Fale Conosco

Sobre o que é sua mensagem?

O que você acha do novo visual?

Você gostou?