Python3中类的命名空间

时间:2017-08-13 17:52:37

标签: python python-3.x class namespaces

我是Python新手,我想知道是否有任何方法可以将方法聚合到子空间'中。我的意思是类似于这种语法:

smth = Something()
smth.subspace.do_smth()
smth.another_subspace.do_smth_else()

我正在编写一个API包装器,我将会有很多非常相似的方法(只有不同​​的URI),所以我将它们放在几个引用API请求类别的子空间中会很好。换句话说,我想在类中创建名称空间。我不知道这在Python中是否可行,并且知道在Google中要查找的内容。

我将不胜感激。

2 个答案:

答案 0 :(得分:4)

执行此操作的一种方法是将subspaceanother_subspace定义为返回分别提供do_smthdo_smth_else的对象的属性:

class Something:
    @property
    def subspace(self):
        class SubSpaceClass:
            def do_smth(other_self):
                print('do_smth')
        return SubSpaceClass()

    @property
    def another_subspace(self):
        class AnotherSubSpaceClass:
            def do_smth_else(other_self):
                print('do_smth_else')
        return AnotherSubSpaceClass()

你想做什么:

>>> smth = Something()
>>> smth.subspace.do_smth()
do_smth
>>> smth.another_subspace.do_smth_else()
do_smth_else

根据您打算使用这些方法的内容,您可能希望SubSpaceClass成为单身人士,但我怀疑性能提升是否值得。

答案 1 :(得分:0)

几年前我有这个需求并想出了这个:

class Registry:
    """Namespace within a class."""

    def __get__(self, obj, cls=None):
        if obj is None:
            return self
        else:
            return InstanceRegistry(self, obj)

    def __call__(self, name=None):

        def decorator(f):
            use_name = name or f.__name__
            if hasattr(self, use_name):
                raise ValueError("%s is already registered" % use_name)
            setattr(self, name or f.__name__, f)
            return f

        return decorator


class InstanceRegistry:
    """
    Helper for accessing a namespace from an instance of the class.

    Used internally by :class:`Registry`. Returns a partial that will pass
    the instance as the first parameter.
    """

    def __init__(self, registry, obj):
        self.__registry = registry
        self.__obj = obj

    def __getattr__(self, attr):
        return partial(getattr(self.__registry, attr), self.__obj)


# Usage:

class Something:
    subspace = Registry()
    another_subspace = Registry()

@MyClass.subspace()
def do_smth(self):
    # `self` will be an instance of Something
    pass

@MyClass.another_subspace('do_smth_else')
def this_can_be_called_anything_and_take_any_parameter_name(obj, other):
    # Call it `obj` or whatever else if `self` outside a class is unsettling
    pass

运行时:

>>> smth = Something()
>>> smth.subspace.do_smth()
>>> smth.another_subspace.do_smth_else('other')

这与 Py2 和 Py3 兼容。在 Py3 中可以进行一些性能优化,因为 __set_name__ 告诉我们命名空间的名称并允许缓存实例注册表。