Python 3中类内的空格

yyyllmsg  于 4个月前  发布在  Python
关注(0)|答案(3)|浏览(64)

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

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

字符串
我正在写一个API Package 器,我会有很多非常相似的方法(只是URI不同),所以我想把它们放在几个引用API请求类别的子空间中会很好。换句话说,我想在一个类中创建命名空间。我不知道这在Python中是否可能,也不知道在Google中应该找什么。
我将感激任何帮助。

dm7nw8vv

dm7nw8vv1#

一种方法是将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成为单例,但我怀疑这样做是否值得。

fbcarpbf

fbcarpbf2#

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

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__告诉我们命名空间的名称,并允许缓存示例注册表。

ufj5ltwl

ufj5ltwl3#

一个简单的方法是使用SimpleNamespace

from types import SimpleNamespace

class Something:
    @staticmethod
    def _did_something(input):
        print(input)

    subspace = SimpleNamespace(
        my_var="stuff",
        do_something=_did_something
    )

字符串
简单用途:

>>> f = Something()
>>> f.subspace.my_var
stuff

>>> f.subspace.do_something("hello")
hello


在这种情况下,不需要引用内部类变量的项可以与@staticmethod定义一起使用,并且也可以在没有示例化的情况下操作:

>>> Something.subspace.my_var
stuff

>>> Something.subspace.do_something("goodbye")
goodbye


对于更复杂的操作,需要引用另一个值,类需要示例化,以便可以设置内部参数:

from types import SimpleNamespace

class Something:
    def __init__(self):
        # must be assigned after class instantiation
        self.other_subspace.tell_secrets = self._other_func

    @staticmethod
    def _did_something(input):
        print(input)

    subspace = SimpleNamespace(
        my_var="stuff",
        do_something=_did_something
    )

    def _other_func(self,input):
        print(self.other_subspace.secret + " and " + input)

    other_subspace = SimpleNamespace(
        secret="mayonaise",
        sauce="duck",
        tell_secrets=None  #placeholder, set after instantiation
    )


在使用中,可以在创建对象后引用这些值:

>>> f = Something()
>>> f.other_subspace.sauce
duck

>>> f.other_subspace.tell_secrets("ketchup")
mayonaise and ketchup

相关问题