用户验证
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
@requires_auth
def addition_func(x):
"""Do some math."""
return x + x
其中@wraps(f) 是因为 这里的函数被decorated替代了。它重写了我们函数的名字和注释文档(docstring)。
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
带参数的装饰器
记录log
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写入内容
with open(logfile, 'a') as opened_file:
# 现在将日志打到指定的logfile
opened_file.write(log_string + '\n')
return func(*args, **kwargs)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
pass
描述
super() 函数是用于调用 父类(超类) 的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
代码一:
class A:
def __init__(self):
print("Enter A")
print("Leave A")
class B(A):
def __init__(self):
print("Enter B")
A.__init__(self)
print("Leave B")
class C(A):
def __init__(self):
print("Enter C")
A.__init__(self)
print("Leave C")
class D(A):
def __init__(self):
print("Enter D")
A.__init__(self)
print("Leave D")
class E(B, C, D):
def __init__(self):
print("Enter E")
B.__init__(self)
C.__init__(self)
D.__init__(self)
print("Leave E")
E()
结果为:
Enter E
Enter B
Enter A
Leave A
Leave B
Enter C
Enter A
Leave A
Leave C
Enter D
Enter A
Leave A
Leave D
Leave E
class A:
def __init__(self):
print("Enter A")
print("Leave A")
class B(A):
def __init__(self):
print("Enter B")
super(B, self).__init__()
print("Leave B")
class C(A):
def __init__(self):
print("Enter C")
super(C, self).__init__()
print("Leave C")
class D(A):
def __init__(self):
print("Enter D")
super(D, self).__init__()
print("Leave D")
class E(B, C, D):
def __init__(self):
print("Enter E")
super(E, self).__init__()
print("Leave E")
E()
结果为:
Enter E
Enter B
Enter C
Enter D
Enter A
Leave A
Leave D
Leave C
Leave B
Leave E
Python内置的@property装饰器就是负责把一个方法变成属性的
装饰器(decorator)可以给函数动态加上功能,对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的。
利用@property还可以只定义 只读 属性,既只定义getter方法;
setter方法可以认为是 可写 属性
class Person(object):
def __init__(self, name, age):
self.__name = name
self._age = age
# 访问器 - getter方法
@property
def name(self):
return self.__name
# 访问器 - getter方法
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self, age):
self._age = age
# 修改器 - setter方法
@name.setter
def name(self, name):
self.__name = name
def main():
person = Person('王大锤', 12)
print(person.name)
print(person.age)
person.name = 'zzk'
person.age = '25'
print(person.name)
print(person.age)
D:\PycharmProjects\untitled\venv\Scripts\python.exe D:/PycharmProjects/untitled/test.py
王大锤
12
zzk
25
定义一个property,在编译期间,编译器会生成实例变量,getter方法、setter方法,这些方法是通过自动合成(autosynthesize)的方式生成并添加到类中。
实际上,一个类经过编译后,会生成变量列表ivar_list,方法列表,method_list。每添加一个属性,在变量列表ivar_list会添加对应的变量,如_name,在方法列表method_list中会添加对应的setter和getter方法。
首先,我们先理解一下动态语言与静态语言的一个不同:
动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改
python是一个动态语言。如果我们想要限制class运行后的实例属性,就需要__slots__方法
class Slots(object):
__slots__ = ("name", "gilrfirend")
def __init__(self):
self.name = 'zzk'
slote = Slots()
print(slote.name)
slote.gilrfirend = "lyw"
print(slote.gilrfirend)
slote.age =25
print(slote.age)
没有在__slote__中的属性会报错 如:
/usr/local/bin/python3.6 /home/dysec/zzk-word/test.py
zzk
lyw
Traceback (most recent call last):
File "/home/dysec/zzk-word/test.py", line 13, in <module>
slote.age =25
AttributeError: 'Slots' object has no attribute 'age'
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
class Slots(object):
__slots__ = ("name", "gilrfirend")
def __init__(self):
self.name = 'zzk'
class TestSlote(Slots):
def __init__(self):
pass
a = TestSlote()
a.age = 'zzk'
print(a.age)
#结果
/usr/local/bin/python3.6 /home/dysec/zzk-word/test-zzk/day002.py
zzk
Process finished with exit code 0
class Slots(object):
def __init__(self):
self.name = None
class TestSlote(Slots):
__slots__ = ("age", "gilrfirend")
def __init__(self):
pass
a = TestSlote()
a.age = '25'
print(a.age)
a.name = 'zzk'
print(a.name)
#结果
/usr/local/bin/python3.6 /home/dysec/zzk-word/test-zzk/day002.py
25
zzk
Process finished with exit code 0