如果没有直接的解决方案,这可能有点棘手,但我也会对更复杂的解决方案感到满意:
我有一个实例绑定数据描述符绑定到我想作为函数参数传递而不被评估(即__get__()
执行)的全局实例。在此代码示例中,它不起作用,并且描述符将10
类型的当前值传递int
给函数参数,而不是其自身:
class RevealAccess(object):
"""A 'instance binding data descriptor' that sets and returns values
normally and prints a message logging their access.
The `x`-value is stored in the instance dictionary `my_instance.__dict__`.
"""
def __init__(self, init_value=None):
self.init_value = init_value
def __get__(self, instance, owner):
value = getattr(instance, self.__name__ + '_value')
print('I AM A DATA-DESCRIPTOR retrieving `{}` value: {}'.format(self.__name__, value))
return value
def __set__(self, instance, value):
print('I AM A DESCRIPTOR updating `{}` to value: {}'.format(self.__name__, value))
setattr(instance, self.__name__ + '_value', value)
class MyClass(object):
x = RevealAccess(init_value=10)
def __new__(cls):
instance = object.__new__(cls)
for desc_name in [key for key in cls.__dict__.keys() if isinstance(cls.__dict__[key], RevealAccess)]:
cls.__dict__[desc_name].__name__ = desc_name
instance.__dict__[desc_name + '_value'] = cls.__dict__[desc_name].init_value
return instance
my_instance = MyClass()
def func_with_descriptor_as_argument(descriptor_arg):
print('\n\nINSIDE the function `descriptor_arg=my_instance.x`results in: {}'.format(descriptor_arg))
print('`type(descriptor_arg)`: {}'.format(type(descriptor_arg)))
print('Changing `my_instance.x` value results in:')
descriptor_arg = 5
print('INSIDE the function after changing `my_instance.x` = {}\n\n'.format(descriptor_arg))
if __name__ == '__main__':
print('\n\nOUTSIDE the function `my_instance.x`: {}'.format(my_instance.x))
print('Changing `my_instance.x` value results in:')
my_instance.x = 5
print('OUTSIDE the function after changing `my_instance.x` = {}\n\n'.format(my_instance.x))
print('Reset:')
my_instance.x = 10
func_with_descriptor_as_argument(descriptor_arg=my_instance.x)
输出是:
I AM A DATA-DESCRIPTOR retrieving `x` value: 10
OUTSIDE the function `my_instance.x`: 10
Changing `my_instance.x` value results in:
I AM A DESCRIPTOR updating `x` to value: 5
I AM A DATA-DESCRIPTOR retrieving `x` value: 5
OUTSIDE the function after changing `my_instance.x` = 5
Reset:
I AM A DESCRIPTOR updating `x` to value: 10
I AM A DATA-DESCRIPTOR retrieving `x` value: 10
INSIDE the function `descriptor_arg=my_instance.x`results in: 10
`type(descriptor_arg)`: <class 'int'>
Changing `my_instance.x` value results in:
INSIDE the function after changing `my_instance.x` = 5
我明白它不是这样工作的。但我想要的是my_instance.__dict__['x_value']
在函数内部操作全局实例字典值。我必须对许多实例和函数重复这一点,并且实际的描述符也在做其他事情(在这个例子中,它只打印“我是......”但在我的例子中,它是例如类型检查、触发其他进程等),所以不希望直接进行字典操作。它必须由描述符完成。
问题
我可以构建某种描述符,可以将一种引用传递给行为等效的函数参数吗?
至今
我一直在寻找不同的选择:
- 单独传递
my_instance
和字符串名称x
或作为元组并在函数内部使用getattr()
,setattr()
。我不喜欢它,因为它是一个框架,对任何人都不好。 - 重载描述符,让它检测它是否通过例如
inspect
someAST
-package 传递给函数,然后在重载的内部构建适当的引用__get__()
并返回它。我可以管理检测部分,但我不知道参考的外观如何?将其包装在另一个描述符中?
最后,函数参数应该像直接可调用的描述符一样在函数内部工作,但获取/设置全局字典my_instance.__dict__['x_value']
(并执行提到的所有其他内容)。
我很高兴有任何想法并期待讨论!