为 class 的所有实例重置由描述符缓存的 属性
Reset property cached by descriptor for all instances of class
我想在多个 class 实例之间共享 requests
会话,并且还能够为所有此类实例重置会话。
所以我有 disconnect
重置所有实例会话的方法:
import requests
class CachedSession:
def __init__(self):
self._initialized = None
def __get__(self, *args, **kwargs):
if self._initialized is None:
self._initialized = self.connect()
return self._initialized
def connect(self):
session = requests.session()
session.headers = {}
session.proxies = {}
session.verify = False
return session
class SomeApi:
session = CachedSession()
def __init__(self):
self.api_key = '123'
def disconnect(self):
self.__class__.session.close()
self.__class__.session = None
def request(self):
print(f'making request using session ID {id(self.session)}')
some_api1 = SomeApi()
some_api2 = SomeApi()
some_api1.request()
some_api1.request()
some_api2.request()
some_api1.disconnect()
some_api1.request()
some_api1.request()
some_api2.request()
# prints OK:
# making request using session ID 1291988425360
# making request using session ID 1291988425360
# making request using session ID 1291988425360
# making request using session ID 140726378118360
# making request using session ID 140726378118360
# making request using session ID 140726378118360
但这是正确的做法吗?
不得不使用 __class__
感觉有点老套,但如果我删除它,只会重置实例会话。
我使用实例方法(disconnect
)重置所有其他实例也感觉不完全正确。
然后我不喜欢 connect
和 disconnect
属于不同的 classes,理想情况下我希望它们都在 CachedSession
描述符中(但是我怎么调用 disconnect
呢?)
要使用单例实例实现 CachedSession
,您应该将其定义为 class 属性
Having to use __class__
feels a little hackish, but if I remove it, only instance session will get reset.
而不是 __class__
属性 您也可以将方法定义为 @classmethod
如下所示
class CachedSession:
_session = None
def __get__(self, *args, **kwargs):
return self.connect()
@classmethod
def connect(cls):
if not cls._session:
cls._session = requests.session()
cls._session.headers = {}
cls._session.proxies = {}
cls._session.verify = False
return cls._session
@classmethod
def disconnect(cls):
if cls._session:
cls._session.close()
cls._session = None
Then I do not like the fact that connect and disconnect belong to different classes, ideally I would like to have them both on the CachedSession descriptor (but how do I call disconnect then?)
如您所见,disconnect
已经是 CachedSession
的 @classmethod
,这意味着它也可以更改任何 class 属性作为 _session
。因此,在断开会话后,class 的所有实例都将断开连接,而 __get__
尚未被调用。要断开会话,只需调用 CachedSession.disconnect()
.
class SomeApi:
session = CachedSession()
def request(self):
print(f'making request using session ID {id(self.session)}')
some_api1 = SomeApi()
some_api2 = SomeApi()
some_api1.request() # making request using session ID 139839142708616
some_api1.request() # making request using session ID 139839142708616
some_api2.request() # making request using session ID 139839142708616
CachedSession.disconnect()
some_api1.request() # making request using session ID 139839142240040
some_api1.request() # making request using session ID 139839142240040
some_api2.request() # making request using session ID 139839142240040
我想在多个 class 实例之间共享 requests
会话,并且还能够为所有此类实例重置会话。
所以我有 disconnect
重置所有实例会话的方法:
import requests
class CachedSession:
def __init__(self):
self._initialized = None
def __get__(self, *args, **kwargs):
if self._initialized is None:
self._initialized = self.connect()
return self._initialized
def connect(self):
session = requests.session()
session.headers = {}
session.proxies = {}
session.verify = False
return session
class SomeApi:
session = CachedSession()
def __init__(self):
self.api_key = '123'
def disconnect(self):
self.__class__.session.close()
self.__class__.session = None
def request(self):
print(f'making request using session ID {id(self.session)}')
some_api1 = SomeApi()
some_api2 = SomeApi()
some_api1.request()
some_api1.request()
some_api2.request()
some_api1.disconnect()
some_api1.request()
some_api1.request()
some_api2.request()
# prints OK:
# making request using session ID 1291988425360
# making request using session ID 1291988425360
# making request using session ID 1291988425360
# making request using session ID 140726378118360
# making request using session ID 140726378118360
# making request using session ID 140726378118360
但这是正确的做法吗?
不得不使用 __class__
感觉有点老套,但如果我删除它,只会重置实例会话。
我使用实例方法(disconnect
)重置所有其他实例也感觉不完全正确。
然后我不喜欢 connect
和 disconnect
属于不同的 classes,理想情况下我希望它们都在 CachedSession
描述符中(但是我怎么调用 disconnect
呢?)
要使用单例实例实现 CachedSession
,您应该将其定义为 class 属性
Having to use
__class__
feels a little hackish, but if I remove it, only instance session will get reset.
而不是 __class__
属性 您也可以将方法定义为 @classmethod
如下所示
class CachedSession:
_session = None
def __get__(self, *args, **kwargs):
return self.connect()
@classmethod
def connect(cls):
if not cls._session:
cls._session = requests.session()
cls._session.headers = {}
cls._session.proxies = {}
cls._session.verify = False
return cls._session
@classmethod
def disconnect(cls):
if cls._session:
cls._session.close()
cls._session = None
Then I do not like the fact that connect and disconnect belong to different classes, ideally I would like to have them both on the CachedSession descriptor (but how do I call disconnect then?)
如您所见,disconnect
已经是 CachedSession
的 @classmethod
,这意味着它也可以更改任何 class 属性作为 _session
。因此,在断开会话后,class 的所有实例都将断开连接,而 __get__
尚未被调用。要断开会话,只需调用 CachedSession.disconnect()
.
class SomeApi:
session = CachedSession()
def request(self):
print(f'making request using session ID {id(self.session)}')
some_api1 = SomeApi()
some_api2 = SomeApi()
some_api1.request() # making request using session ID 139839142708616
some_api1.request() # making request using session ID 139839142708616
some_api2.request() # making request using session ID 139839142708616
CachedSession.disconnect()
some_api1.request() # making request using session ID 139839142240040
some_api1.request() # making request using session ID 139839142240040
some_api2.request() # making request using session ID 139839142240040