Python:获取方法使用的属性列表

时间:2019-07-17 19:39:20

标签: python python-3.x python-internals

我想要一个(Python 3.7+)函数,给定一个(类,方法)对,它将为我提供执行该方法的计算所需的属性列表。

我知道一般情况下可能很难解决(甚至不可能),所以我将处理涉及大多数情况的事情(如果可以解决无法安全处理的情况,我会很高兴的)检测到(并且用户对此进行了警告)。

请考虑以下内容:

def func(obj):
    return obj.a + obj.b

class A:
    e = 2
    def __init__(self, a=0, b=0, c=1, d=10):
        self.a = a
        self.b = b
        self.c = c
        self.d = d

    def target_method(self, x=3):
        t = func(self)
        tt = self.other_method(t)
        return x * tt / self.e

    def other_method(self, x=1):
        return self.c * x

我想要的attr_used_by_method函数将执行以下操作:

>>> attr_used_by_method(cls=A, method_name='target_method')
['a', 'b', 'c', 'e']

因为:当对象传递给a时使用bfuncc方法使用other_method,而{{1 }}用于计算返回值。但是属性self.e对于计算机d并不是必需的,因此不会返回。

我搜索了target_methodinspect软件包,看它们是否可以完成工作,但是看起来只有trace才能正确完成工作。

ast个书呆子在那里吗?

对于上下文:我想要这样一个功能的原因是能够创建一个“特殊的json序列化”,该序列只能序列化执行对象的特定方法所需的那些属性。

3 个答案:

答案 0 :(得分:1)

class Tracker:
    """
    Tracks the attribute access right after `start_track` is set to True.

    Add this to __metaclass__ for any class that you need to track attributes for given a
    target method.
    """
    attrs_to_ignore = []
    attr_used = []
    start_track = False

    def __getattribute__(self, item):
        """
        Inspect getter for tracking the attributes accessed.
        """
        if item not in ['on_access']:
            self.on_access(item)
        return super().__getattribute__(item)

    def __setattr__(self, key, value):
        """
        Inspect setter for tracking the attributes accessed.
        """
        if self.start_track:
            self.on_access(key)

        super().__setattr__(key, value)

    def on_access(self, key):
        """
        on attribute access, record attribute if and only if its not from
        core attribute or `attrs_to_ignore` set to class.
        """
        if key in ['start_track', 'attr_used', 'on_access', 'attrs_to_ignore'] or key in self.attrs_to_ignore:
            return
        if self.start_track:
            self.attr_used.append(key)


def attr_used_by_method(cls, method_name, method_params):
    """
    Tracks the access to attributes within an execution.
    """
    # create meta class with the above tracker and `cls` from parameters.
    tracker = type('Tracker', (Tracker, cls), dict(cls.__dict__, **Tracker.__dict__))()
    tracker.attrs_to_ignore = [func for func in dir(tracker) if callable(getattr(tracker, func))]
    if hasattr(tracker, method_name):
        candidate_method = getattr(tracker, method_name)
        # Now, we want to track attributes.
        tracker.start_track = True
        candidate_method(**method_params)
        attr_used = tracker.attr_used.copy()
        tracker.attr_used = []
        return attr_used
    else:
        # Error class/obj do not have that method.
        return 1

答案 1 :(得分:0)

您可以跟踪其他函数正在使用的变量,并将它们存储在列表中,然后通过命名函数“ attr_used_by_method”返回该列表

答案 2 :(得分:0)

ast module可以做到。如果我们假设源存储在名为for l in f: print(l) fullweb=web+l links.append(fullweb) ft.writelines(fullweb) 的变量中(可以从文件中读取):

source

这失去了获得唯一性和友好的显示顺序的顺序,但是如果您不需要唯一性但想要排序,则可以只使用列表推导或生成器表达式来代替集合推导。结果import ast root = ast.parse(source) names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name)}) 为:

list