Python 从内部类引用父对象实例

Python 从内部类引用父对象实例,python,python-3.x,inner-classes,Python,Python 3.x,Inner Classes,我正在尝试创建一个语法友好的库,它不需要用户不断地传入凭据或键入冗余或过多的语句。我的策略是关注库语法的外观,然后设计库以实现这种功能。我知道我可以实现以下目标: api = Api(user="admin", pswd="blahblah") new_order = api.Order() new_order.status = "pending" api.create(new_order) api.order_assign_user(new_order, user) existing_or

我正在尝试创建一个语法友好的库,它不需要用户不断地传入凭据或键入冗余或过多的语句。我的策略是关注库语法的外观,然后设计库以实现这种功能。我知道我可以实现以下目标:

api = Api(user="admin", pswd="blahblah")

new_order = api.Order()
new_order.status = "pending"
api.create(new_order)
api.order_assign_user(new_order, user)

existing_order = api.get_order(orderId=12345)
existing_order.status = "shipped"
api.update(existing_order)
class Api(object):
    def __init__(self, user=None, pswd=None):
        self.user = user
        self.pswd = pswd

    class Order(api):
        def __init__ (self, status=None):
            self.status = status

    def create(self, x):
        auth = Auth(self.user, self.pswd)
        # use authorization credentials to create data remotely
        return x

    def update(self, x):
        auth = Auth(self.user, self.pswd)
        # use authorization credentials to update data from remote
        return x

    def get_order(self, orderId=None):
        auth = Auth(self.user, self.pswd)
        # use authorization credentials to update data from remote
        return order
使用类似以下内容:

api = Api(user="admin", pswd="blahblah")

new_order = api.Order()
new_order.status = "pending"
api.create(new_order)
api.order_assign_user(new_order, user)

existing_order = api.get_order(orderId=12345)
existing_order.status = "shipped"
api.update(existing_order)
class Api(object):
    def __init__(self, user=None, pswd=None):
        self.user = user
        self.pswd = pswd

    class Order(api):
        def __init__ (self, status=None):
            self.status = status

    def create(self, x):
        auth = Auth(self.user, self.pswd)
        # use authorization credentials to create data remotely
        return x

    def update(self, x):
        auth = Auth(self.user, self.pswd)
        # use authorization credentials to update data from remote
        return x

    def get_order(self, orderId=None):
        auth = Auth(self.user, self.pswd)
        # use authorization credentials to update data from remote
        return order

但我希望能够使用以下语句:

new_order.create() # instead of api.create(new_order)

new_order.assign_user(user) # instead of api.order_assign_user(new_order, user)

existing_order = api.Order.get(orderId=12345) # returns retrieved Order Instance
这给我带来了一个问题: 如何让
Order()
实例访问创建它的
Api()
实例的属性?如果不能访问这些属性,任何像“user”和“pswd”这样的属性都将无法访问(requests.get()调用需要它们)

我尝试了函数和类的各种变体来实现这一点,但始终无法解决这个问题。这是我所能达到的最接近的目标:

class Api(object):
    def __init__(self, user=None, pswd=None):
        self.user = user
        self.pswd = pswd

    class Order(api):
        def __init__ (self, status=None):
            self.status = status

        @classmethod
        def get(cls, value):
            return cls(status=value)

        def create(self):
            auth = Auth(self.user, self.pswd) 
            # these credentials need to come from the Api() instance?, not self
            return x

        def update(self):
            auth = Auth(self.user, self.pswd) 
            # these credentials need to come from the Api() instance?, not self
            return x

这可能吗?还是我走错了方向?我曾经考虑过将其变成一个模块,但这似乎也不是一个有效的选项。

Python中的内部类只是单独的类,它们的实例不会以任何方式自动与外部类的实例关联

我建议一种解决方案,
Order
的构造函数将
Api
实例作为参数,并使用该实例:

class Api(object):
    def __init__(self, user=None, pswd=None):
        self.user = user
        self.pswd = pswd

class Order(object):
    def __init__(self, api, status=None):
        self.api = api
        self.status = status

    @classmethod
    def get(cls, api, value):
        return cls(api, status=value)

    def create(self):
        auth = Auth(self.api.user, self.api.pswd)
        return x

    def update(self):
        auth = Auth(self.api.user, self.api.pswd)
        return x

Python中的内部类只是单独的类,它们的实例不会以任何方式自动与外部类的实例关联

我建议一种解决方案,
Order
的构造函数将
Api
实例作为参数,并使用该实例:

class Api(object):
    def __init__(self, user=None, pswd=None):
        self.user = user
        self.pswd = pswd

class Order(object):
    def __init__(self, api, status=None):
        self.api = api
        self.status = status

    @classmethod
    def get(cls, api, value):
        return cls(api, status=value)

    def create(self):
        auth = Auth(self.api.user, self.api.pswd)
        return x

    def update(self):
        auth = Auth(self.api.user, self.api.pswd)
        return x

这演示了我认为您想要做的事情的基本实现,我发现这比我在评论您的问题时想到的
\uuuu get\uuuuu
\uu set\uuuuu
黑客技术要好

import requests

class Order:
    def __init__(self, user:str, passwd: str):
        self.session = requests.Session()
        self.session.auth = (user, passwd)
        self.status = None

    # This is only to make the class callable, since the class is
    # already instantiated in Api init calling it again would raise an exception
    def __call__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
        return self

    def get(self):
        response = self.session.get('https://httpbin.org/basic-auth/my_user/my_pass')
        print(response.text)

    def post(self):
        response = self.session.post('https://httpbin.org/post', data={'status': self.status})
        print(response.text)


class Api:
    def __init__(self, user: str, passwd: str):
        self.Order = Order(user, passwd)

这演示了我认为您想要做的事情的基本实现,我发现这比我在评论您的问题时想到的
\uuuu get\uuuuu
\uu set\uuuuu
黑客技术要好

import requests

class Order:
    def __init__(self, user:str, passwd: str):
        self.session = requests.Session()
        self.session.auth = (user, passwd)
        self.status = None

    # This is only to make the class callable, since the class is
    # already instantiated in Api init calling it again would raise an exception
    def __call__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
        return self

    def get(self):
        response = self.session.get('https://httpbin.org/basic-auth/my_user/my_pass')
        print(response.text)

    def post(self):
        response = self.session.post('https://httpbin.org/post', data={'status': self.status})
        print(response.text)


class Api:
    def __init__(self, user: str, passwd: str):
        self.Order = Order(user, passwd)

这是可行的,但是我必须输入
Order.get(api,orderId=12345)
,这虽然不是超级问题,但不是我想要实现的目标。虽然这似乎是我的解决方案。如果我是你,我会在Api类中创建一个
get_order
方法,该方法将返回
order(Api=self,…)
,然后使用该顺序。另一个无关的注意事项是,
camelCased
名称(如你的注释中的
orderId
)不是pythonic,您应该使用
snake\u case
。我知道,但是为其创建的API使用CamelCase作为其属性(JSON)。我认为保持一致性会比较容易混淆,也因此我不必在两者之间进行转换/交换。这是可行的,但我必须键入
Order.get(api,orderId=12345)
,这虽然不是超级问题,但不是我试图实现的目标。虽然这似乎是我的解决方案。如果我是你,我会在Api类中创建一个
get_order
方法,该方法将返回
order(Api=self,…)
,然后使用该顺序。另一个无关的注意事项是,
camelCased
名称(如你的注释中的
orderId
)不是pythonic,您应该使用
snake\u case
。我知道,但是为其创建的API使用CamelCase作为其属性(JSON)。我认为保持一致会比较容易混淆,也因此我不必在两者之间进行转换/交换。这是可能的,但我现在没有时间给出正确的答案,如果还没有人发布,我会稍后回来回答,同时,看看
\uuuu get\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>神奇方法以及它们如何接收
实例
参数,你可以在
Api
类中实例化你的
订单
类,并利用这个,如果还没有人发布,我稍后会回来回答,同时看一下
\uuuu get\uuuuuuu
\uuuu set\uuuuu
魔术方法以及它们如何接收
实例
参数,您可以在
Api
类中实例化您的
Order
类,并利用此方法。我能够使用此方法完全实现我想要的。谢谢。我能用这个来完成我想要的。非常感谢。