对不起我的英语不好.我想创建一个装饰器方法,可以检查每个步骤方法并将其写入db.
这是我的方法:
class Test:
@StepStatusManager.logger_steps("GET_LIST") # TypeError: logger_steps() missing 1 required positional argument: 'type'
def get_mails(self):
print("GET_MAIL")
这是我的装饰类:
class StepStatusManager:
def __init__(self):
self.db = DB()
def logger_steps(self, type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
self.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
jdehesa..
5
您正在尝试logger_steps
直接从类中调用实例方法,StepStatusManager
而Python将该值"GET_LIST"
作为self
参数而不是type
.您应该创建一个实例,StepStatusManager
然后让装饰器调用实例的方法.它可以很简单:
manager = StepStatusManager()
class Test:
@manager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
现在,这是创建类的实例,然后在实例上调用方法,而不是尝试直接从类中调用该方法.您现在可以使用它manager
来装饰任意数量的方法.此外,这将使所有修饰的方法使用相同StepStatusManager
,但如果你想,你可以创建不同的实例,并使用它们来装饰不同的方法; self.db
如果需要,可以让你使用不同的方法.
另一种方法可能是db
在类中使用变量,而是创建logger_steps
一个类方法:
class StepStatusManager:
db = DB()
@classmethod
def logger_steps(cls, type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
cls.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
class Test:
@StepStatusManager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
但请注意,这不太灵活,因为如果您需要,它将不允许您使用不同的管理器装饰方法.此外,这大部分相当于拥有一个StepStatusManager
模块,而不是一个类,其中db
是一个模块变量,并且logger_steps
是一个模块函数,如果你想要这个功能,它可能会更清晰:
# StepStatusManager.py
# ...
db = DB()
def logger_steps(type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
cls.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
# test.py
import StepStatusManager
class Test:
@StepStatusManager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
同样,这可能更简单,但不太灵活,因为您提出的第一个基于类的解决方案.
编辑:
只是为了完整性和比较,这里是另一个版本,类似于一个版本,@classmethod
但是使用@staticmethod
(以了解这两个装饰器之间的细微差别,检查关于它的许多SO问题之一,例如@staticmethod之间有什么区别和@classmethod?或@classmethod和@staticmethod的初学者意义?):
class StepStatusManager:
db = DB()
@staticmethod
def logger_steps(type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
StepStatusManager.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
class Test:
@StepStatusManager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
由于它经常与发生@classmethod
和@staticmethod
,差别相当小.如果您使用继承,或者如果您使用的是元类,装饰器或类似的东西,它们的行为可能会有所不同,但除此之外它们几乎相同.
1> jdehesa..:
您正在尝试logger_steps
直接从类中调用实例方法,StepStatusManager
而Python将该值"GET_LIST"
作为self
参数而不是type
.您应该创建一个实例,StepStatusManager
然后让装饰器调用实例的方法.它可以很简单:
manager = StepStatusManager()
class Test:
@manager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
现在,这是创建类的实例,然后在实例上调用方法,而不是尝试直接从类中调用该方法.您现在可以使用它manager
来装饰任意数量的方法.此外,这将使所有修饰的方法使用相同StepStatusManager
,但如果你想,你可以创建不同的实例,并使用它们来装饰不同的方法; self.db
如果需要,可以让你使用不同的方法.
另一种方法可能是db
在类中使用变量,而是创建logger_steps
一个类方法:
class StepStatusManager:
db = DB()
@classmethod
def logger_steps(cls, type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
cls.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
class Test:
@StepStatusManager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
但请注意,这不太灵活,因为如果您需要,它将不允许您使用不同的管理器装饰方法.此外,这大部分相当于拥有一个StepStatusManager
模块,而不是一个类,其中db
是一个模块变量,并且logger_steps
是一个模块函数,如果你想要这个功能,它可能会更清晰:
# StepStatusManager.py
# ...
db = DB()
def logger_steps(type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
cls.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
# test.py
import StepStatusManager
class Test:
@StepStatusManager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
同样,这可能更简单,但不太灵活,因为您提出的第一个基于类的解决方案.
编辑:
只是为了完整性和比较,这里是另一个版本,类似于一个版本,@classmethod
但是使用@staticmethod
(以了解这两个装饰器之间的细微差别,检查关于它的许多SO问题之一,例如@staticmethod之间有什么区别和@classmethod?或@classmethod和@staticmethod的初学者意义?):
class StepStatusManager:
db = DB()
@staticmethod
def logger_steps(type):
def logger_steps(func):
@functools.wraps(func)
def wrapper(*args):
try:
func(*args)
StepStatusManager.db.setStatus(type)
except BaseException as e:
print(e)
return wrapper
return logger_steps
class Test:
@StepStatusManager.logger_steps("GET_LIST")
def get_mails(self):
print("GET_MAIL")
由于它经常与发生@classmethod
和@staticmethod
,差别相当小.如果您使用继承,或者如果您使用的是元类,装饰器或类似的东西,它们的行为可能会有所不同,但除此之外它们几乎相同.