从内部引用父对象实例 class
Referencing parent object instance from inner class
我正在尝试创建一个语法友好的库,它不需要用户不断地输入凭据或键入冗余或过多的语句。我的策略是专注于我希望库语法看起来如何,然后设计库以这种方式运行。我知道我可以执行以下操作:
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 中的内部 class 只是单独的 class,它们的实例不会以任何方式自动与外部 class 的实例相关联。
我会建议一个解决方案,其中 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
这演示了我认为您想做的事情的基本实现,我发现这比我在评论您的问题时想到的 __get__
、__set__
骇客更好
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)
我正在尝试创建一个语法友好的库,它不需要用户不断地输入凭据或键入冗余或过多的语句。我的策略是专注于我希望库语法看起来如何,然后设计库以这种方式运行。我知道我可以执行以下操作:
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 中的内部 class 只是单独的 class,它们的实例不会以任何方式自动与外部 class 的实例相关联。
我会建议一个解决方案,其中 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
这演示了我认为您想做的事情的基本实现,我发现这比我在评论您的问题时想到的 __get__
、__set__
骇客更好
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)