The directory is as follows:
1. What is a decorator?
2. How to use decorators?
3. Built-in decorators
First, what is decoration?
A decorator, as its name suggests, is a function that enhances the functionality of a function or class.
That might be a little tricky to say.
For example: how to calculate the execution time of a function?
Here, you need to calculate the time of the add function.
# function
def add(a, b):
res = a + b
return resCopy the code
You might write it like this
import time
def add(a, b)
start_time = time.time()
res = a + b
exec_time = time.time() - start_time
print("The add function takes: {}".format(exec_time))
return resCopy the code
At this point, the boss asks you to calculate the time of the subtraction function (sub). Without decorators, you have to write a subtraction code again.
def sub(a, b)
start_time = time.time()
res = a - b
exec_time = time.time() - start_time
print("Sub function, the time is: {}".format(exec_time))
return resCopy the code
It’s cumbersome and inflexible, and if the code that counts the time changes, you have to change every function.
So, we need to introduce decorators.
The code after using the decorator looks like this
import time
Define the decorator
def time_calc(func):
def wrapper(*args, **kargs):
start_time = time.time()
f = func(*args,**kargs)
exec_time = time.time() - start_time
return f
return wrapper
# Use decorators
@time_calc
def add(a, b):
return a + b
@time_calc
def sub(a, b):
return a - bCopy the code
Doesn’t it look fresher?
What decorators do: Enhance functions. Specifically, they can decorate functions as well as classes.
How decorators work: Functions are first-class citizens of Python, and functions are objects.
Define decorator
def decorator(func):
def wrapper(*args,**kargs):
You can customize the parameters passed in
print(func.__name__)
Return the call of the method name argument passed in
return func(*args,**kargs)
Return the name of the inner function
return wrapperCopy the code
Second, use decorators
Assume that the decorator is a defined decorator.
Method 1: Don’t use the @ symbol
No arguments are passed to the decoratorF = decorator(function name)When the decorator passes a parameterF = (decorator(argument))(function name)Copy the code
Method two: use the syntactic sugar @ symbol
# defined decorator
@decorator
def f():
pass
Execute the decorated function
f()Copy the code
Decorators may or may not take parameters.
Decorators that pass no parameters themselves (using a two-tier function-defined decorator)
def login(func):
def wrapper(*args,**kargs):
print('Function name :%s'% func.__name__)
return func(*args,**kargs)
return wrapper
@login
def f():
print('inside decorator! ')
f()
# output:
# >> function name :f
# >> Function itself: Inside decorator!Copy the code
Decorators that pass in parameters themselves (using a three-tier function-defined decorator)
def login(text):
def decorator(func):
def wrapper(*args,**kargs):
print('%s----%s'%(text, func.__name__))
return func(*args,**kargs)
return wrapper
return decorator
# is equivalent to ==> (login(text))(f) ==> return wrapper
@login('this is a parameter of decorator')
def f():
print('2019-06-13')
# is equivalent to the = = > (login (text)) (f) () = = > call wrapper () and returns the f ()
f()
# output:
# => this is a parameter of decorator----f
# = > 2019-06-13Copy the code
Three, built-in decorator
There are three common built-in decorators: @Property, @StaticMethod, and @classMethod
@property
To use an in-class method as a property, you must have a return value, equivalent to a getter;
If the @func.setter decorator is not defined, it is read-only
class Car:
def __init__(self, name, price):
self._name = name
self._price = price
@property
def car_name(self):
return self._name
# car_name Is a read-write attribute
@car_name.setter
def car_name(self, value):
self._name = value
# car_price is a read-only property
@property
def car_price(self):
return str(self._price) + '万'
benz = Car('benz'30),print(benz.car_name) # benz
benz.car_name = "baojun"
print(benz.car_name) # baojun
print(benz.car_price) # 300000Copy the code
@staticmethod
Static methods that don’t need to represent their own object’s self and CLS arguments of their own class, just like using a function.
@classmethod
Class method. No self argument is required, but the first argument needs to be a CLS argument representing its own class.
example
class Demo(object):
text = "A comparison of the three methods"
def instance_method(self):
print("Call instance method")
@classmethod
def class_method(cls):
print("Calling class methods")
print("Access class attributes in class methods text: {}".format(cls.text))
print("Call instance method instance_method: {} in class method".format(cls().instance_method()))
@staticmethod
def static_method():
print("Calling static methods")
print("Access class attributes in static methods text: {}".format(Demo.text))
print("Call instance method instance_method: {} in static method".format(Demo().instance_method()))
if __name__ == "__main__":
Instantiate the object
d = Demo()
Objects can access instance methods, class methods, and static methods
Access the text property through the object
print(d.text)
Call instance methods from objects
d.instance_method()
Call a class method from an object
d.class_method()
Call static methods from objects
d.static_method()
Classes can access class methods, static methods
Access the text property through the class
print(Demo.text)
Call class methods through classes
Demo.class_method()
Call a static method from a class
Demo.static_method()Copy the code
@staticMethod and @classMethod
In the above example, we can see that,
The difference between
When defining a staticmethod or a class method, the @staticmethod decorates a staticmethod that requires the class name to access a class attribute or call an instance method.
The @classmethod method decorates the classmethod by passing a CLS parameter that represents the class, thus avoiding hard-coding the class name by hand.
Both static and class methods are actually written the same way, usually through the class name. Static method () or class name. Class method ().
Static and class methods can also be called with instantiated objects, but to distinguish them from instance methods, it is best to call static and class methods with classes.
Usage scenarios
So, when you define a class,
Use @staticMethod if you don’t need a class-related attribute or method.
If you need a class-specific property or method, and you want to indicate that the method is generic to the entire class rather than object specific, you can use the @classMethod method.
There are also some other github summaries: test development interview resources, review material summaries
If you’re interested, check it out.