Я создаю одноэлементный декоратор для тестов, но когда я спрашиваю, является ли объект экземпляром исходного класса, он возвращает false.
В этом примере я украшаю класс счетчика, чтобы создать синглтон, поэтому каждый раз, когда я получаю значение, оно возвращает следующее число, независимо от того, какой экземпляр объекта его вызывает.
код в значительной степени работает, но функция isinstance, кажется, не работает, я пытался использовать functools.update_wrapper, но я не знаю, могу ли я получить функцию isinstance для распознавания Singleton как Counter (в следующем коде) до тех пор, пока я запрашиваю Counter код фактически возвращает Singleton.
декоратор
def singleton(Class):
class Singleton:
__instance = None
def __new__(cls):
if not Singleton.__instance:
Singleton.__instance = Class()
return Singleton.__instance
#update_wrapper(Singleton, Class,
# assigned=('__module__', '__name__', '__qualname__', '__doc__', '__annotation__'),
# updated=()) #doesn't seems to work
return Singleton
оформленный класс
@singleton
class Counter:
def __init__(self):
self.__value = -1
self.__limit = 6
@property
def value(self):
self.__value = (self.__value + 1) % self.limit
return self.__value
@property
def limit(self):
return self.__limit
@limit.setter
def limit(self, value):
if not isinstance(value, int):
raise ValueError('value must be an int.')
self.__limit = value
def reset(self):
self.__value = -1
def __iter__(self):
for _ in range(self.limit):
yield self.value
def __enter__(self):
return self
def __exit__(self,a,b,c):
pass
тест
counter = Counter()
counter.limit = 7
counter.reset()
[counter.value for _ in range(2)]
with Counter() as cnt:
print([cnt.value for _ in range(10)]) #1
print([counter.value for _ in range(5)]) #2
print([val for val in Counter()]) #3
print(Counter) #4
print(type(counter)) #5
print(isinstance(counter, Counter)) #6
вывод:
#1 - [2, 3, 4, 5, 6, 0, 1, 2, 3, 4]
#2 - [5, 6, 0, 1, 2]
#3 - [3, 4, 5, 6, 0, 1, 2]
#4 - <class '__main__.singleton.<locals>.Singleton'>
#5 - <class '__main__.Counter'>
#6 - False
(без оболочки обновления)
#1 - [2, 3, 4, 5, 6, 0, 1, 2, 3, 4]
#2 - [5, 6, 0, 1, 2]
#3 - [3, 4, 5, 6, 0, 1, 2]
#4 - <class '__main__.Counter'>
#5 - <class '__main__.Counter'>
#6 - False