我是Python新手,我想知道是否有任何方法可以将方法聚合到子空间'中。我的意思是类似于这种语法:
smth = Something()
smth.subspace.do_smth()
smth.another_subspace.do_smth_else()
我正在编写一个API包装器,我将会有很多非常相似的方法(只有不同的URI),所以我将它们放在几个引用API请求类别的子空间中会很好。换句话说,我想在类中创建名称空间。我不知道这在Python中是否可行,并且知道在Google中要查找的内容。
我将不胜感激。
答案 0 :(得分:4)
执行此操作的一种方法是将subspace
和another_subspace
定义为返回分别提供do_smth
和do_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__
告诉我们命名空间的名称并允许缓存实例注册表。