0

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

我怎样才能做到这一点?

class SomeClass(object):

    def __init__(self, foo, bar):

        self.foo = foo
        self.bar = bar

        convert_all_instance_fields_into_properties(self)   # implementation ?
4

2 回答 2

1

可以很容易地使用 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

于 2019-06-19T12:27:22.447 回答
0

Python中没有“私有”之类的东西。如果你想并且足够努力,你可以提取任何东西。

有 2 个级别的半私人:

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

大多数时候,你只需要一个下划线——人们只有在他们认为他们真的需要它时才会访问它。

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

请记住,即使使用“getter”,您也将返回一个对象,除非您自己返回一个副本。重新思考你的设计,用 Python 思考,而不是“私有”和“getters”。;)


编辑:

好像我误解了这个问题。

标有@property装饰器的函数将返回不带括号的函数来调用它们(spam.eggs,而不是spam.eggs())并且是“只读的”(你可以这样做bacon = spam.eggs但不能spam.eggs = bacon)。

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

  • 如果有足够的决心,一切都可以访问
  • 使用下划线很好地要求人们不要访问该值
  • 如果你的 getter 属性返回一个可变对象,它内部仍然是可变的(只有引用会保持不变),例如eggs.list = []不会工作,但eggs.list.append("spam")会!
于 2019-06-19T09:02:43.313 回答