提供类中的方法列表以供在其外部使用

时间:2016-05-26 15:09:07

标签: python python-3.x

如何在类中提供方法列表以供在其外部使用?

我正在寻找

当我从扩展更高级别的类创建一个对象时,我想得到一个特定方法的列表,一些"元数据"其中,并且能够在课外召唤他们。

示例:

def params(params):
    def params_fn(f):
        def params_dec(*args, **kwargs):
            for i in params:
                f.__setattr__(i, params[i])
            return f(*args, **kwargs)
        return params_dec
    return params_fn

class Channel:
    queue = None
    # some code & docs omitted

    def __init__(self, queue):
        self.queue = queue

    def start(self):
        while True:
            if not self.check():
                break


class channelA(Channel):

    extra_methods = ['get_users', 'get_groups']

    def start(self):
        # omitted
        pass

    def __internal_method(self, d):
        # omitted
        pass

    @params({"name": "Get users", "desc": "Get a list of users", "icon": "user-plus"})
    def get_users(self):
        # omitted
        return [i for i in self.queue if i.type = 1]

    @params({"name": "Get groups", "desc": "Get a list of groups", "icon": "group-plus"})
    def get_groups(self):
        # omitted
        return [i for i in self.queue if i.type = 2]


q = []
ch = channelA(q)

# some code goes here
# it may be something like
# fns = ch.get_extra_fns()
# or anything similar

for fnName in fns:
    print("Callable name:", fnName)
    print("Name:", fns[fnName].name)
    print("Description:", fns[fnName].desc)
    print("Icon ID:", fns[fnName].icon)
    print("Result:")
    print(ch.call(fns[fnName])())

有可能实现这样的目标吗?

3 个答案:

答案 0 :(得分:1)

您不需要装饰方法的包装器,因为您只设置方法对象的属性。为了识别你的方法,我建议为这些方法设置一个特殊属性,迭代所有类方法并选择那些具有这种特殊方法集的方法:

def special(**kw):
    def mark(function):
        function.is_special = True
        function.keywords = kw
        return function
    return mark

class Channel:
    def __init__(self, queue):
        self.queue = queue

    def start(self):
        while True:
            if not self.check():
                break


class ChannelA(Channel):
    def start(self):
        # omitted
        pass

    @special(icon="users.png")
    def get_users(self):
        # omitted
        return [i for i in self.queue if i.type == 1]

    @special(hint="don't feed the trolls")
    def get_groups(self):
        # omitted
        return [i for i in self.queue if i.type == 2]

ch = ChannelA(q)

for methodname in dir(type(ch)):
    method = getattr(ch, methodname)
    if getattr(method, 'is_special', False):
        print("Callable name:", method.__name__)
        print("Keywords:", method.keywords)
        print("Result:", method())

答案 1 :(得分:0)

def get_extra_fns(self):
    fns = {}
    for i in self.extra_methods:
        fns['i'] = self.__getattribute__(i)
    return fns

答案 2 :(得分:0)

Python 3:

import types
import inspect


class A:
    def a(self): 
        pass


class B(A):
    def b(self, bool_param, int_param): 
        pass

b = B()

for member_name in dir(B):
    member = getattr(B, member_name)
    if isinstance(member, types.FunctionType):
        member(b, True)  # as illustrated by you... this is hardcoded

        argspec = inspect.getargspec(member)

        args_for_call = {}
        for argname in argspec.args:
            if argname == 'bool_param':
                args_for_call['bool_param'] = True
            if argname == 'int_param':
                args_for_call['int_param'] = 3

        member(b, **args_for_call)   # This is less hardcoded