優れたアプリケーションは、デコレータの閉鎖が拡大しています!
ディアン引数なしのデコレータ
1.1デコレータは何ですか
デバイスは、ツールを参照して、プログラムの機能は、機能ツールを持つことである、それはデコレータオブジェクトに追加機能を追加するためにデコレータを指します。したがって、デコレータの定義は、関数の定義があるが、関数の機能は他の機能に追加機能を追加するために使用されます。
それに注意してください。
デコレータ自体は実際に呼び出すことができる任意のオブジェクトにすることができます
オブジェクトを装飾するためには、任意の呼び出し可能オブジェクトすることができ
1.2なぜ使用デコレータ
私たちはライン上のプロジェクトを持っている場合は、我々は特定のメソッドを変更する必要がありますが、我々は、使用方法、あなたはデコレータを使用することができます。この時間を変更する必要はありません。ソフトウェアの保守がオープンクローズの原則に従わなければならないので、ソフトウェアのソースコードのソフトウェアのオンライン操作、保守および修正が閉じられると、拡張機能は、オープンを参照していること。
デコレータを達成するための2つの原則に従う必要があります。
ソースコードを変更しない装飾的なオブジェクトは、
装飾されたオブジェクトの呼び出しが変更されることはありません
、実際に上記の2つの原則のデコレータを、以下の前提の下で飾ら対象に新機能を追加しています。
1.3デコレータを使用する方法
ソースコードの変更
import time
def index():
start = time.time()
print('welcome to index')
time.sleep(1)
end = time.time()
print(F"index run time is {start-end}")
index()
welcome to index index run time is -1.0008180141448975
重複したコードを書きます
import time
def index():
print('welcome to index')
time.sleep(1)
def f2():
print('welcome to index')
time.sleep(1)
start = time.time()
index()
end = time.time()
print(F"index run time is {start-end}")
start = time.time()
f2()
end = time.time()
print(F"f2 run time is {start-end}")
welcome to index index run time is -1.0046868324279785 welcome to index f2 run time is -1.000690221786499
最初のパラメータ渡しモード:方法を変更通話
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
start = time.time()
func()
end = time.time()
print(f"{func} time is {start-end}")
time_count(index)
welcome to index <function index at 0x102977378> time is -1.000748872756958
二番目のパラメータ渡しモード:パケット機能 - アウトソーシング
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
func()
end = time.time()
print(f"{func} time is {start-end}")
return wrapper
# f = time_count(index)
# f()
index = time_count(index) # index为被装饰函数的内存地址,即index = wrapper
index() # wrapper()
welcome to index <function index at 0x102977730> time is -1.0038220882415771
1.4完璧なデコレータ
デコレータ以上、最後の呼び出し指数()、実際には、のラッパー()、および値を返し、元のインデックスは()、ラッパーは、()の戻りであるべき値とインデックスと同じ値を返す場合、そのための時間を()呼び出しているとき、戻り値は、つまり、私たちは、元のインデックス()とラッパー()メソッドを同期する必要があります。
import time
def index():
print('welcome to index')
time.sleep(1)
return 123
def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
res = func()
end = time.time()
print(f"{func} time is {start-end}")
return res
return wrapper
index = time_count(index)
res = index()
print(f"res: {res}")
welcome to index <function index at 0x102977620> time is -1.0050289630889893 res: 123
元のインデックス()メソッドは、質量参加を必要とする場合、この機能を達成することができない前に、我々は原因ラッパー()=指数()をデコレータので、パラメータを渡すためのラッパー()メソッドを与えます。
import time
def index():
print('welcome to index')
time.sleep(1)
return 123
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
return name
def time_count(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func} time is {start-end}")
return res
return wrapper
home = time_count(home)
res = home('egon')
print(f"res: {res}")
welcome egon to home page <function home at 0x102977378> time is -1.0039079189300537 res: egon
1.5デコレータのシンタックスシュガー
装飾的な機能には、単に上記の、および独立したライン@デコレータ名の上に書かれています
import time
def time_count(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func} time is {start-end}")
return res
return wrapper
@time_count # home = time_count(home)
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
return name
@time_count # index = time_count(index)
def index():
print('welcome to index')
time.sleep(1)
return 123
res = home('egon')
print(f"res: {res}")
welcome egon to home page <function home at 0x102977620> time is -1.0005171298980713 res: egon
1.6デコレータテンプレート
ダブルデコレータテンプレート
def deco(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) return res return wrapper
三つの装飾テンプレート(パラメータデコレータがあります)
3層までの一般的なパラメータは、より多くの層を設定することもできますが、それは、十分な装飾層3自体はもちろん、機能性のニーズを追加したい達成するために、意味がありませんが、また、より多くの装飾を達成するパフォーマンス関数やクラスを与えることができます関数デコレータは異なるケースのシナリオを実現するために
、事前にそのハの下で...
ディアンは、2つのパラメータデコレータを持っています
参照デコレータがあるが、今のは、登録ユーザーのログインデコレータを実装してみましょう - いいえ、パラメータ設定デコレータ2つだけの層は、このセクションでは、三セット・デコレーターを教えてくれません。
import time
current_user = {'username': None}
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
if user == 'nash' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
return wrapper
@login
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
return name
@login
def index():
print('welcome to index')
time.sleep(1)
return 123
res = index()
username: nash password: 123 login successful welcome to index
上記ログイン登録については、当社のユーザーに関する情報が正常にログインそれらのメモリを書き込みます。しかし、業界では、ユーザー情報は、テキスト内に存在でのMySQL、それらをMongoDBのが、我々は唯一のユーザーは、ユーザーからの情報を提出することを可能にする認証することができます。したがって、我々は、上記のデコレータを書き換えることができます。
import time
current_user = {'username': None}
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
engine = 'file'
if engine == 'file':
print('base of file')
if user == 'nash' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql')
elif engine == 'mongodb':
print('base of mongodb')
else:
print('default')
return wrapper
@login
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
@login
def index():
print('welcome to index')
time.sleep(1)
res = index()
username: nash password: 123 base of file login successful welcome to index
2.1 3閉鎖
def f1(y):
def f2():
x = 1
def f3():
print(f"x: {x}")
print(f"y: {y}")
return f3
return f2
f2 = f1(2)
f3 = f2()
f3()
x: 1 y: 2
今では、ファイルの種類であれば、我々はその後、ユーザ認証を聞かせて、我々は変更する必要がある、と私たちは、ユーザーが動的パスワードのユーザーを取得する方法を決定する必要があります。したがって、我々はデコレータを持っているパラメータを使用することができます。
import time
current_uesr = {'username': None}
def auth(engine='file'):
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
if engine == 'file':
print('base of file')
if user == 'nash' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql, please base of file')
elif engine == 'mongodb':
print('base of mongodb, please base of file')
else:
print('please base of file')
return wrapper
return login
@auth(engine='mysql')
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
@auth(engine='file')
def index():
print('welcome to index')
time.sleep(1)
res = index()
username: nash password: 123 base of file login successful welcome to index
2つのデコレータとして、パラメータが一定の場所funcを持っている必要がありますが、3つのデコレータは、この制限を解除しました。私達はちょうどちょうど3つのデコレータ複数のパラメータにいくつかのパラメータを追加する必要があり、上記の3つのデコレータの単一のパラメータを使用することはできません。3へのデコレータ、余分な層実際には役に立ちません。
結婚や装飾は、クラスに適用されます
:デコレータ何口コミ
デコレータ定義:基本的機能(高階関数)、機能は他の機能(オブジェクト)に新しい機能を追加することです
次のようにクラスのデコレータは基本的に動作します:
def deco(cls):
print('类的装饰器=========》')
print('='*20)
return cls
@deco #====> Foo = deco(Foo)
class Foo:
pass
第二に、上記のシンプルな装飾は引数はありません、そして今、私たちは、パラメータを追加します
def cls_decorator(**kwargs): #支持传入参数(属性和对应的值),字典形式
def deco(cls):
for key,val in kwargs.items():
setattr(cls,key,val) #给类设置对应的属性和值
return cls
return deco
@cls_decorator(name='Menawey',age=24,gender='male') # 1 运行cls_decorator(...),返回deco;2 @deco===> Peolple = deco(People)
#相当于给People类设置了name、age、gender属性
class People:
pass
print(People.__dict__) #查看被装饰过的类的属性字典
これによって動的に異なるクラスのインスタンス化の彼の属性で増加
第三に、記述子と組み合わせて
使用すると、クラス属性とtype属性を追加するなど、多くの機能を実行することができます装飾的な組み立てとクラス記述子を使用して定義することができます。
#描述符
class Desc:
def __init__(self,key,value_type):
self.key = key
self.value_type = value_type
def __get__(self, instance, owner):
return instance.__dict__[self.key]
def __set__(self, instance, value):
if not isinstance(value,self.value_type):
raise TypeError('%s 传入的类型不是 %s'%(self.key,self.value_type))
instance.__dict__[self.key] = value
def __delete__(self, instance):
instance.__dict__.pop(self.key)
#装饰器
def cls_decorator(**kwargs): #支持传入参数(属性和对应的值),字典形式
def deco(cls):
for key,val in kwargs.items(): #这里需要用到描述符对属性进行代理,但是val是指定的类型,所以要用Desc(key,val)来描述为对应的值
setattr(cls,key,Desc(key,val)) #给类设置对应的属性和值
return cls
return deco
@cls_decorator(name=str,age=int,gender=str,salary=float) #使用装饰器
#被装饰和描述的类
class People:
def __init__(self,name,age,gender,salary):
self.name = name
self.age = age
self.gender = gender
self.salary = salary
p1 = People('Menawey',24,'male',11.1) #因为gender属性指定的是sstr,但是TypeError: age 传入的类型不是 <class 'int'>
print(People.__dict__)
四のディアン脳大きなワイドオープン
デコレータとして何?? !!パイソンクラス!!! ??
参考リンク:
https://blog.csdn.net/qq_29767317/article/details/80799410
da
#重写了__call__方法,类的对象就能够被调用,直接使用t()来调用类,并打印__call__方法里面的内容
class Test(object):
print("--------test1----------")
def __call__(self, *args, **kwargs):
print(da) #注意一点,__call__方法里面的是最后执行。
def eat(self):
print("-----------eat-------------")
print("---------test2---------")
t = Test()
t()
結果:
D:\ python3.6 \ pythonw.exe F:/ Pythonプロジェクト/ 09Day / 03pythonアドバンスト/ 01クラスデコレータの.pyとして
-------- ---------- TEST1
TEST2 --------- ---------
--------- ---------テスト
デコレータとしてクラス:
class Test(object):
def __init__(self,func):
print("-------初始化-------")
print("func name is %s" %func.__name__)
self.__func = func #类的私有属性self.__func也指向了test1函数的内存地址。
def __call__(self, *args, **kwargs): #test1 = Test(test1) #调用类的对象。就会调用call方法。
print("------装饰器中的功能-------")
self.__func() #self.__func指向了函数test1的内存地址。这句话相当于执行test1()函数。
#使用类作为装饰器,需要重写Call方法,没有调用test1()方法的时候,执行代码得到下面的结果
# -------初始化-------
# func name is test1
@Test #相当于 test1 = Test(test1) 也相当于func指向了下面函数test1的名字, 前面的test1指向了 Test()这个对象。
# 调用test1对象的时候相当于调用类方法Test(),调用类方法必调用__call方法,调用call方法的时候,先执行 print("------装饰器中的功能-------")
#然后在执行self.__func() ,因为self.__func函数指向的是test1函数,test1()相当于执行self.__func().
def test1():
print("----test1---------")
test1() #调用test1
D:\ python3.6 \ pythonw.exe F: / Pythonのデコレータの.pyとしてプロジェクト/ 09Day / 03pythonアドバンスト/ 02クラス
------- -------初期
FUNC名がtest1のIS
--- ---デコレータ機能-------
---- --------- TEST1