将实例字段转换为属性

Convert Instance Fields into Properties

我想将对象的所有实例字段转换为属性(仅限 getter),以便使它们成为只读的。这些字段可能由子类定义。

我怎样才能做到这一点?

class SomeClass(object):

    def __init__(self, foo, bar):

        self.foo = foo
        self.bar = bar

        convert_all_instance_fields_into_properties(self)   # implementation ?

Python中没有"private"这样的东西。如果你想并且足够努力,你可以提取任何东西。

有2个等级semi-private:

  • 一个供内部使用的下划线前缀,通常在外部可访问 - 但大多数 IDE 会在其下划线并警告不推荐的做法
  • pseudo-private 的两个下划线前缀,如果有人真的想要它仍然可以访问但丑陋

大多数时候,您只需要一个下划线 - 人们只有在认为真正需要它时才会访问它。

在我正在使用的代码中,我看到两个下划线仅用作封装延迟加载属性的一种方式(一个下划线是 "getter" 并检查变量是否已加载)。

请记住,即使使用 "getter",您也将是 return 一个对象,除非您自己 return 一个副本。重新考虑您的设计,考虑 Python,而不是 "private" 和 "getters"。 ;)


编辑:

好像我误解了问题。

@property 装饰器标记的函数将 return 不带括号调用它们(spam.eggs,而不是 spam.eggs())并且是 "read-only"(您可以做 bacon = spam.eggs 但不做 spam.eggs = bacon).

但我的其余评论仍然有效:

  • 只要有足够的决心,一切都触手可及
  • 使用下划线礼貌地要求人们不要访问该值
  • 如果您的 getter 属性 return 是一个可变对象,它在内部仍然是可变的(只有引用会保持不变),例如eggs.list = [] 不行,但是 eggs.list.append("spam") 可以!

可以很容易地使用 python 内置函数实现只读字段:

class X:

    def __init__(self, val):
        self.foo = val

    def __setattr__(self, key, value):
        if not hasattr(self, key):  # only for first set
            super(X, self).__setattr__(key, value)
        else:
            raise ValueError


def main():
    x = X('bar')
    y = X('baz')

    assert x.foo == 'bar'
    assert y.foo == 'baz'

    # raises ValueError
    x.foo = 'Raise an error!'

如果要指定哪些字段是只读的

class X:

    readonly = ['foo']

    def __init__(self, val):
        self.foo = val

    def __setattr__(self, key, value):
        if key in self.readonly and not hasattr(self, key):
            super(X, self).__setattr__(key, value)
        else:
            raise ValueError