例如,我有一个类:
from datetime import datetime
class Book:
def __init__(self, contents):
self.last_accessed = datetime.now()
self.content = contents
def add_content(self, addition):
self.content += str(addition)
def replace_content(self, replacement):
self.content = replacement
def read_content(self):
return self.content
我希望这个类能够记录下上次访问图书的时间,例如:
Mybook = Book("Hello") # Last accessed = datetime.now()
Mybook.add_content(" World") # Last accessed = datetime.now(), which should be later than the previous datetime.now()
Mybook.read_content() # Last accessed should be later than when I added " World" to Mybook.content
我怎么才能让Mybook.last_accessed在我每次修改我的书的时候都改变呢?
提前谢谢。
发布于 2020-07-03 07:20:33
from datetime import datetime
class Book:
def __init__(self, contents):
self.__update_datetime()
self.content = contents
def __update_datetime(self):
self.last_accessed = datetime.now()
def add_content(self, addition):
self.content += str(addition)
self.__update_datetime()
def replace_content(self, replacement):
self.content = replacement
self.__update_datetime()
def read_content(self):
self.__update_datetime()
return self.content
Mybook = Book("Hello")
print(Mybook.last_accessed) # 2020-07-03 10:17:25.596847
Mybook.add_content(" World")
print(Mybook.last_accessed) # 2020-07-03 10:17:25.596905
Mybook.read_content()
print(Mybook.last_accessed) # 2020-07-03 10:17:25.596917
发布于 2020-07-03 07:39:15
一个优雅的解决方案可能是利用装饰器。
下面的函数可以用作装饰器,因为它是一个将一个函数作为单个参数并返回另一个函数的函数。
def set_time(func):
@functools.wraps(func)
def wrapper_set_time(self, *args, **kwargs):
self.last_accessed = datetime.now()
return func(self, *args, **kwargs)
return wrapper_set_time
这允许在调用修饰函数之前和/或之后执行操作。
在您的特定情况下,修饰后的函数将在进行计算之前自动执行self.last_accessed = datetime.now()
。
这就是如何装饰Book
类的方法:
class Book:
# Don't use @set_time for linters
def __init__(self, contents):
self.last_accessed = datetime.now()
self.content = contents
@set_time
def add_content(self, addition):
self.content += str(addition)
@set_time
def replace_content(self, replacement):
self.content = replacement
@set_time
def read_content(self):
return self.content
你看,在方法定义之前添加一个@set_time
是很费钱的。
请注意,我们并不是在修饰__init__
方法,这只是为了让linters不会因为不隐藏类的创建而抱怨访问类实例的.last_accessed
属性。
这就是结果:
book = Book("Hello")
print(book.last_accessed) # 2020-07-03 09:33:04.999283
book.add_content(" World")
print(book.last_accessed) # 2020-07-03 09:33:04.999359
book.read_content()
print(book.last_accessed) # 2020-07-03 09:33:04.999399
这是一个简单的示例,您可能希望使其更简洁。
例如,装饰器只设置了.last_accessed
属性,但您可能希望轻松地更改该名称。为此,您可以使用可以接受参数的装饰器。
有关更多见解,请参阅Real Python Primer on Python Decorators。
https://stackoverflow.com/questions/62710168
复制