如何检查类方法是否返回self?

2024-04-26 05:03:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我想列出给定类中返回self的所有方法。你知道吗

我知道在Python中,不可能在函数运行之前检查它的返回类型。你知道吗

也许可以检查函数体(源)中的return self,或者有其他方法?你知道吗

我需要它与python3.5和更高版本的工作

编辑:

这个类(不是完整的代码)是gremlinpython库的一部分。你知道吗

class GraphTraversal(Traversal):
    def __init__(self, graph, traversal_strategies, bytecode):
        super(GraphTraversal, self).__init__(graph, traversal_strategies, bytecode)
    def __getitem__(self, index):
        if isinstance(index, int):
            return self.range(long(index), long(index + 1))
        elif isinstance(index, slice):
            low = long(0) if index.start is None else long(index.start)
            high = long(sys.maxsize) if index.stop is None else long(index.stop)
            if low == long(0):
                return self.limit(high)
            else:
                return self.range(low,high)
        else:
            raise TypeError("Index must be int or slice")
    def __getattr__(self, key):
        return self.values(key)

    def V(self, *args):
        self.bytecode.add_step("V", *args)
        return self

    def addE(self, *args):
        self.bytecode.add_step("addE", *args)
        return self

    def addV(self, *args):
        self.bytecode.add_step("addV", *args)
        return self

它允许像这样使用fluent API查询图形数据库

g.V().hasLabel('label').has('id','xxx').addE('relation').to(g.V().hasLabel('otherlabel').has('id','yyy')

到目前为止,我能得到这样的方法:

from inspect import getsourcelines, signature

def contains_return_self(f):   
   lines, _ = getsourcelines(f)   
   return any("return self" in line for line in lines)

def check_signature(f):
   sig = signature(f)
   if(len(sig.parameters) == 2 
      and 'self' in sig.parameters.keys()
      and 'args' in sig.parameters.keys()):
      return True
   return False

fluent_methods = [
   method_name for method_name in dir(GraphTraversal) 
      if callable(getattr(GraphTraversal, method_name)) 
         and ('__' not in method_name)
         and contains_return_self(getattr(GraphTraversal, method_name))
         and check_signature(getattr(GraphTraversal, method_name))]

我想返回所有具有以下签名的方法:

def foo(self, *args)
    # some code
    return self 

Tags: and方法nameinselfindexreturnif
1条回答
网友
1楼 · 发布于 2024-04-26 05:03:54

尽管像@RafaelC一样,我强烈怀疑这可能是一个XY Problem,但这里有一些东西——部分基于^{}模块——似乎是可行的(在这种方法固有的限制范围内)。为了进行测试,我添加了Traversal基类的定义以及一些不匹配的方法到它和派生的GraphTraversal类中。你知道吗

from collections import namedtuple
import inspect
import re

class Traversal:
    def inherited_method1(self, *args):
        return self

    def inherited_method2(self, foobar):
        return foobar + 13

class GraphTraversal(Traversal):
    def __init__(self, graph, traversal_strategies, bytecode):
        super(GraphTraversal, self).__init__(graph, traversal_strategies, bytecode)
    def __getitem__(self, index):
        if isinstance(index, int):
            return self.range(long(index), long(index + 1))
        elif isinstance(index, slice):
            low = long(0) if index.start is None else long(index.start)
            high = long(sys.maxsize) if index.stop is None else long(index.stop)
            if low == long(0):
                return self.limit(high)
            else:
                return self.range(low,high)
        else:
            raise TypeError("Index must be int or slice")

    def __getattr__(self, key):
        return self.values(key)

    def non_match1(self, *args):
        self.bytecode.add_step("V", *args)
        return 42

    def non_match2(self, arg1, arg2):
        self.bytecode.add_step("V", *args)
        return self

    def V(self, *args):
        self.bytecode.add_step("V", *args)
        return self

    def addE(self, *args):
        self.bytecode.add_step("addE", *args)
        return self

    def addV(self, *args):
        self.bytecode.add_step("addV", *args)
        return self

### Introspect class
DUNDER = re.compile(r"^_{2,}\w*_{2,}\Z", re.UNICODE)
MethInfo = namedtuple('MethInfo', ['name', 'value'])

methods = [MethInfo(*pair) for pair in inspect.getmembers(GraphTraversal, inspect.isfunction)
                if not DUNDER.match(pair[0])]

def contains_return_self(meth_info):
    src = inspect.getsource(meth_info.value)
    for line in src.splitlines():
        if 'return self' in line.strip():
            return True
    else:
        return False

def check_signature(meth_info):
    sig = inspect.signature(meth_info.value)
    return str(sig) == '(self, *args)'

fluent_methods = [meth_info.name for meth_info in methods
                    if contains_return_self(meth_info) and check_signature(meth_info)]

print('fluent_methods:', fluent_methods)

输出:

fluent_methods: ['V', 'addE', 'addV', 'inherited_method1']

相关问题 更多 >