Python 仅公开其所包装的类的属性子集的包装类

Python 仅公开其所包装的类的属性子集的包装类,python,python-3.x,object,Python,Python 3.x,Object,我想知道是否有比现在更优雅的方式来公开包装类的属性: class WrapperClass: EXPOSED_ATTRIBUTES = ["a"] def __init__(self): self.wrapped_class = Foo() def print_a(self): print(f"The value of a is :{self.wrapped_class.a}") def __getattr__(self, i

我想知道是否有比现在更优雅的方式来公开包装类的属性:

class WrapperClass:
    EXPOSED_ATTRIBUTES = ["a"]

    def __init__(self):
        self.wrapped_class = Foo()

    def print_a(self):
        print(f"The value of a is :{self.wrapped_class.a}")

    def __getattr__(self, item):
        if item in self.EXPOSED_ATTRIBUTES:
            return getattr(self.wrapped_class, item)
        elif item in self.__dict__:
            return getattr(self, item)
        else:
            raise AttributeError


class Foo:
    def __init__(self):
        self.a = 1
        self.b = 2

编辑:我似乎不清楚我的意图。包装类的目的是在我的代码和第三方库之间创建边界。我只是想减少代码中暴露的属性和方法的数量。

如果您试图用包装类来限制暴露字段的数量,那么您应该利用Python动态生成类的能力。也就是说,创建一个工厂,该工厂生成的新类上只有公开的字段可用

目前,EXPOSED_ATTRIBUTES查找使用的是一个数组,相对来说比直接查找要慢,因为每次调用uu getattr_u时,它必须迭代整个数组,以确保属性是公开的。通过动态生成一个类,您的访问时间将与任何其他类相同,并且它将为您处理所有AttributeError异常

您可以使用该命令创建新类型aka:class。在您的情况下,可以编写如下简单的工厂函数:

def wrap(wrapped, name, exposed_attributes=[]):
  attributes = {attr:wrapped[attr] for attr in exposed_attributes}
  return type(name, (object,), attributes)
这将像这样使用

class SomeClass(object):
  def __init__(self):
    self.name = 'Joe Blow'
    self.age  = 27

WrappedClass = wrap(SomeClass, 'WrappedClass', ['name'])
wrapped_class = WrappedClass()
wrapped_class.name # 'Joe Blow'
wrapped_class.age  # AttributeError

# another wrapper on the same class
AnotherWrappedClass = wrap(SomeClass, 'AnotherWrappedClass', ['age'])
another_wrapped_class = AnotherWrappedClass()
wrapped_class.age  # 27
wrapped_class.name # AttributeError

在代码中,我们使用字典理解来构建属性的dict。每个属性都指向包装类上的一个属性。将返回新类型,然后您可以创建它的实例。新类上只存在暴露的字段,因此尝试访问任何其他属性会抛出与您预期相同的AttributeError。

您所问的问题与您的观点非常接近,可能会产生建议,而不是答案。你希望从中得到什么?你为什么不把一处房产用于一个项目?是否要为哪个类动态定义要转发的属性?目前,您的设置完全是静态的和琐碎的-您只需显式地编写转发。