首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类方法/静态方法可以访问初始调用方的属性吗?

类方法/静态方法可以访问初始调用方的属性吗?
EN

Stack Overflow用户
提问于 2021-05-03 16:22:36
回答 6查看 141关注 0票数 1

为了简单起见,我正在学习并尝试为一些第三方api编写python客户端:

我有两个类: Session,EndpointGroup:

代码语言:javascript
复制
class Session:
    def __init__(self, token=None):
        self.token = token
        self.group1 = EndpointGroup

class EndpointGroup:
    @classmethod
    def ping(cls, token, **kwargs):
        return f'Calling ping() with params: {kwargs} and token {token}'

我有许多包含相同类别api调用的EndpointGroups。

我想让终端用户调用这样的方法:

代码语言:javascript
复制
session = Session(token='123')
r = session.group1.ping(data='somedata') # Calling ping with params: {'data':'somedata'} and token 123

我想把令牌自动/隐式地传递给可调用的,这样用户就不必每次调用就可以调用类似session.group1.ping(data='somedata',token=session.token)之类的东西。

有没有“内置”的解决方案来解决这个问题?因为使用_getattribute_,我只能访问EndpointGroup类,而不能访问调用的方法。

我已经尝试过的:

使用_getattribute_

  • Let会话继承EndpointGroup方法创建EndpointGroup传递会话/令牌的实例(不喜欢解决方案,因为它为每个会话创建了太多实例),但随后,我失去了理想的“接口”,比如session.groupN.method_X到EndpointGroup类中的session.method_X

  • Make在“令牌”,每次调用更改时,方法都可以访问当前调用方(会话)的令牌(不喜欢此解决方案,因为这样我将无法工作asynchronously)

)

EN

回答 6

Stack Overflow用户

发布于 2021-05-03 16:50:03

您可以使用一些代理来充当部分函数:

代码语言:javascript
复制
class PartialProxy:
    def __init__(self, method, **kwargs):
        self.method = method
        self.kwargs = kwargs
        
    def __call__(self, **kwargs):
        k = {**self.kwargs, **kwargs}
        return self.method(**k)
        
class PartialProxyProxy:
    def __init__(self, klass, **kwargs):
        self.klass = klass
        self.kwargs = kwargs
    
    def __getattr__(self, attr):
        return PartialProxy(getattr(self.klass, attr), **self.kwargs)


class Session:
    def __init__(self, token=None):
        self.token = token
        self.group1 = PartialProxyProxy(EndpointGroup, token=token)

class EndpointGroup:
    @classmethod
    def ping(cls, token, **kwargs):
        return f'Calling ping() with params: {kwargs} and token {token}'

session = Session(token='123')
r = session.group1.ping(data='somedata')
print(r)

输出:

代码语言:javascript
复制
Calling ping() with params: {'data': 'somedata'} and token 123
票数 1
EN

Stack Overflow用户

发布于 2021-05-12 10:50:16

代码语言:javascript
复制
class Session:
    def __init__(self, token=None):
        self.token = token
        self.group1 = EndpointGroup

    def __getattribute__(self, item):
        attribute = super(Session, self).__getattribute__(item)
        if isinstance(attribute, type(EndpointGroup)):
            return ProxyEndpointGroup(self.token,attribute)
        else:
            return attribute
代码语言:javascript
复制
import functools
class ProxyEndpointGroup:
    def __init__(self, token, endpoint_group):
        self.token = token
        self.endpoint_group = endpoint_group

    def __getattr__(self, item):
        return functools.partial(getattr(self.endpoint_group,item), token=self.token)
代码语言:javascript
复制
class EndpointGroup:
    @classmethod
    def ping(cls,token, **kwargs):
        return f'Calling ping() with params: {kwargs} and token {token}'
代码语言:javascript
复制
session = Session(token='12345')
r = session.group1.ping(data='endpoint data')
print(r)

>> Calling ping() with params: {'data': 'endpoint data'} and token 12345

通过这种方式,您可以只在调用时创建代理对象,添加令牌param并返回分部方法,最后销毁代理对象。

它解决了您不需要在内存中创建多个不必要的对象的问题,还解决了异步调用作为令牌在每个调用中传递的问题。

票数 1
EN

Stack Overflow用户

发布于 2021-05-07 14:48:18

我看不出为什么ping()应该是一个类方法而不是一个实例方法,如果它是一个实例方法,您的问题就会变得更容易:

代码语言:javascript
复制
class Session:
    def __init__(self, token=None):
        self.token = token
        self.group1 = EndpointGroup(session=self)

将会话传递给EndpointGroup,然后它的实例方法ping可以直接访问令牌:

代码语言:javascript
复制
class EndpointGroup:
    def __init__(self, session):
        self.session = session
    def ping(self, token, **kwargs):
        return f'Calling ping() with params: {kwargs} and token {self.session.token}'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67372387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档