在玩具示例中实现 python 个装饰器
Implementing python decorators in a toy example
我一直在努力寻找一个学习装饰器的用例,我想我找到了一个与我相关的。
我正在使用以下代码。
在文件 class1.py
中我有:
import pandas as pd, os
class myClass():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc1\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
if __name__ == '__main__':
myClass()
在文件class2.py
中我有:
class myClassInAnotherFile():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc2\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
self.Fn2()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
def Fn2(self):
print('something else')
if __name__ == '__main__':
myClassInAnotherFile('DoneFile12)
有没有办法在另一个名为 utilities.py
的文件中定义通用装饰器代码,以便我可以执行以下操作:
文件中需要 class1.py
我有:
import pandas as pd, os
class myClass():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc1\fn.csv'
self.Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
if __name__ == '__main__':
@myDecorator
myClass()
在文件class2.py
中我有:
class myClassInAnotherFile():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc2\fn.csv'
self.Fn1()
self.Fn2()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
def Fn2(self):
print('something else')
if __name__ == '__main__':
@myDecorator
myClassInAnotherFile()
本质上是使用装饰器模仿原始行为。
编辑1:
我希望扩展 class 定义的功能。在两个原始 class 定义中,我重复检查 fnDone
文件的代码,如果它存在,则退出 class。 目标是有一个装饰器来检查 fnDone
文件并在 class 存在时退出。
编辑2:
我也可以将此作为一个函数来执行,但我正在尝试学习如何使用装饰器扩展 class 或方法的功能。
编辑3:
如果我在 class1.py
:
中有以下内容,它会更容易吗?
def myClass():
fnDone = f'C:\user1\Desktop\loc1\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
if __name__ == '__main__':
myClass()
和class2.py
如下:
def myClassInAnotherFile():
fnDone = f'C:\user1\Desktop\loc2\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
self.Fn2()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
def Fn2(self):
print('something else')
if __name__ == '__main__':
myClassInAnotherFile('DoneFile12)
这是一个装饰器,用于检查 运行 您的代码之前文件是否存在:
文件:my_decorator.py
import os
import pandas as pd
def checkDoneDecorator(doneFilename):
def _decorator(decorated):
def _wrapper_function(*args, **kwargs):
if os.path.exists(doneFilename):
return
try:
result = decorated(*args, **kwargs)
finally:
pd.DataFrame({'Done': 1}, index=[0]).to_csv(doneFilename)
return _wrapper_function
return _decorator
文件:class1.py
from my_decorator import checkDoneDecorator
@checkDoneDecorator(doneFilename='C:\user1\Desktop\loc1\fn.csv')
def myClass():
Fn1()
def Fn1():
print('something')
if __name__ == '__main__':
myClass()
文件:class2.py
from my_decorator import checkDoneDecorator
@checkDoneDecorator(doneFilename='C:\user1\Desktop\loc2\fn.csv')
def myClassInAnotherFile():
Fn1()
Fn2()
def Fn1():
print('something')
def Fn2():
print('something else')
if __name__ == '__main__':
myClassInAnotherFile()
一些注意事项:
- 我使用了带有参数
doneFilename
的装饰器,它比简单的装饰器多添加了一层嵌套函数。可以看详细例子here.
- 我把
doneFilename
的写法也包含在装饰器里面,因为文件检查和文件写是相关的。不过这不是强制性的。
- 我从您的示例中删除了
self
参数,因为此示例中并不真正需要 class。如果你真的需要一个 class,请不要把装饰器放在 __init__
上,而是这样做:
class myClass:
@checkDoneDecorator(doneFilename='C:\user1\Desktop\loc1\fn.csv')
def start(self):
self.Fn1()
def Fn1(self):
print('something')
if __name__ == '__main__':
myClass().start()
因为fnDone
是局部变量而不是参数,所以使用装饰器有点尴尬。如果您稍微修改代码以将 fnDone
作为参数传递,则使用装饰器将成为一个更可行的选择。
例如,你可以做一个装饰器来包装对象的构造函数,并检查传入的文件是否存在:
import os.path
from functools import wraps
import pandas as pd
def check_file_exists(f):
@wraps(f)
def _inner(self, fn_done):
if os.path.exists(fn_done):
return
f(self, fn_done)
return _inner
class MyClass:
@check_file_exists
def __init__(self, fn_done) -> None:
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fn_done)
if __name__ == "__main__":
MyClass("fn.csv")
我对@pigeonhands 给出的答案投了赞成票,因为您主要对使用 class 感兴趣。但这就是我使用常规函数实现您的目标的方式,我认为这更有意义。出于与@pigeonhands 提供的相同原因,将 CSV 文件名作为 myclass
函数的参数作为参数名称 fnDone:
是有意义的
import os.path
from functools import wraps
import pandas as pd
def myDecorator(func):
@wraps(func)
def wrapper(fnDone):
if os.path.exists(fnDone):
return
func(fnDone)
return wrapper
@myDecorator
def myClass(fnDone):
Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1():
print('something')
if __name__ == '__main__':
myClass('test1.csv')
我一直在努力寻找一个学习装饰器的用例,我想我找到了一个与我相关的。
我正在使用以下代码。
在文件 class1.py
中我有:
import pandas as pd, os
class myClass():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc1\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
if __name__ == '__main__':
myClass()
在文件class2.py
中我有:
class myClassInAnotherFile():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc2\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
self.Fn2()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
def Fn2(self):
print('something else')
if __name__ == '__main__':
myClassInAnotherFile('DoneFile12)
有没有办法在另一个名为 utilities.py
的文件中定义通用装饰器代码,以便我可以执行以下操作:
文件中需要 class1.py
我有:
import pandas as pd, os
class myClass():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc1\fn.csv'
self.Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
if __name__ == '__main__':
@myDecorator
myClass()
在文件class2.py
中我有:
class myClassInAnotherFile():
def __init__(self):
fnDone = f'C:\user1\Desktop\loc2\fn.csv'
self.Fn1()
self.Fn2()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
def Fn2(self):
print('something else')
if __name__ == '__main__':
@myDecorator
myClassInAnotherFile()
本质上是使用装饰器模仿原始行为。
编辑1:
我希望扩展 class 定义的功能。在两个原始 class 定义中,我重复检查 fnDone
文件的代码,如果它存在,则退出 class。 目标是有一个装饰器来检查 fnDone
文件并在 class 存在时退出。
编辑2: 我也可以将此作为一个函数来执行,但我正在尝试学习如何使用装饰器扩展 class 或方法的功能。
编辑3:
如果我在 class1.py
:
def myClass():
fnDone = f'C:\user1\Desktop\loc1\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
if __name__ == '__main__':
myClass()
和class2.py
如下:
def myClassInAnotherFile():
fnDone = f'C:\user1\Desktop\loc2\fn.csv'
if os.path.exists(fnDone): return
self.Fn1()
self.Fn2()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1(self):
print('something')
def Fn2(self):
print('something else')
if __name__ == '__main__':
myClassInAnotherFile('DoneFile12)
这是一个装饰器,用于检查 运行 您的代码之前文件是否存在:
文件:my_decorator.py
import os
import pandas as pd
def checkDoneDecorator(doneFilename):
def _decorator(decorated):
def _wrapper_function(*args, **kwargs):
if os.path.exists(doneFilename):
return
try:
result = decorated(*args, **kwargs)
finally:
pd.DataFrame({'Done': 1}, index=[0]).to_csv(doneFilename)
return _wrapper_function
return _decorator
文件:class1.py
from my_decorator import checkDoneDecorator
@checkDoneDecorator(doneFilename='C:\user1\Desktop\loc1\fn.csv')
def myClass():
Fn1()
def Fn1():
print('something')
if __name__ == '__main__':
myClass()
文件:class2.py
from my_decorator import checkDoneDecorator
@checkDoneDecorator(doneFilename='C:\user1\Desktop\loc2\fn.csv')
def myClassInAnotherFile():
Fn1()
Fn2()
def Fn1():
print('something')
def Fn2():
print('something else')
if __name__ == '__main__':
myClassInAnotherFile()
一些注意事项:
- 我使用了带有参数
doneFilename
的装饰器,它比简单的装饰器多添加了一层嵌套函数。可以看详细例子here. - 我把
doneFilename
的写法也包含在装饰器里面,因为文件检查和文件写是相关的。不过这不是强制性的。 - 我从您的示例中删除了
self
参数,因为此示例中并不真正需要 class。如果你真的需要一个 class,请不要把装饰器放在__init__
上,而是这样做:
class myClass:
@checkDoneDecorator(doneFilename='C:\user1\Desktop\loc1\fn.csv')
def start(self):
self.Fn1()
def Fn1(self):
print('something')
if __name__ == '__main__':
myClass().start()
因为fnDone
是局部变量而不是参数,所以使用装饰器有点尴尬。如果您稍微修改代码以将 fnDone
作为参数传递,则使用装饰器将成为一个更可行的选择。
例如,你可以做一个装饰器来包装对象的构造函数,并检查传入的文件是否存在:
import os.path
from functools import wraps
import pandas as pd
def check_file_exists(f):
@wraps(f)
def _inner(self, fn_done):
if os.path.exists(fn_done):
return
f(self, fn_done)
return _inner
class MyClass:
@check_file_exists
def __init__(self, fn_done) -> None:
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fn_done)
if __name__ == "__main__":
MyClass("fn.csv")
我对@pigeonhands 给出的答案投了赞成票,因为您主要对使用 class 感兴趣。但这就是我使用常规函数实现您的目标的方式,我认为这更有意义。出于与@pigeonhands 提供的相同原因,将 CSV 文件名作为 myclass
函数的参数作为参数名称 fnDone:
import os.path
from functools import wraps
import pandas as pd
def myDecorator(func):
@wraps(func)
def wrapper(fnDone):
if os.path.exists(fnDone):
return
func(fnDone)
return wrapper
@myDecorator
def myClass(fnDone):
Fn1()
pd.DataFrame({'Done': 1}, index=[0]).to_csv(fnDone)
def Fn1():
print('something')
if __name__ == '__main__':
myClass('test1.csv')