只在类中读取的Python属性

时间:2017-04-05 16:38:34

标签: python attributes

我有一个班级:

class Portfolio:
    def __init__(self, value):
        self.value = value

class GenericStrategy:
    def __init__(self, portfolio: Portfolio):
        self.portfolio = portfolio

    def modify_ptf_value(new_value):
        self.portfolio.value = new_value
        # This should return an error

我将编写一些将继承自GenericStrategy的策略。我希望他们的方法能够读取属性组合但不能修改它,也不能修改它的属性。

我读了一些关于@properties装饰器的内容,但只有当我不想从外面访问属性(及其属性)时它才有效,我仍然可以修改属性(及其属性)来自方法'内部'物体。 有没有办法使属性(及其属性)'只读' __init__方法除外?我的设计是错的,应该重新开始吗?我知道用户不得修改" protected"属性,但我想让它成为防弹。任何想法都被广泛接受,即使它需要对课堂设计进行重大改变。

由于

1 个答案:

答案 0 :(得分:1)

与其他(常用的)编程语言相反, Python 提供了一种关于访问类/实例成员的新方法。例如,没有什么是真正的私有,字段/方法:

  • _开头,是常规字段
  • __开始(最多只有一个_),只是名称被破坏,但仍然可以从课外访问(甚至修改/删除)

所以,最后它是一个常规问题,并且它依赖于编写代码的人。底线是 nothing 会阻止用户访问类/实例的内部。

注意:在其他语言中,访问私有成员也是可能的:有正式支持的方法(如 Reflection ( {em> Java )的[Oracle]: Trail: The Reflection API),或者不受官方支持(需要一些"技巧" - 例如:reinterpret_cast classstruct与{em> C ++ )具有相同结构的class LockedAttribute(object): def __init__(self, name): self._name = name self._set_count = 0 self._set_treshold = 1 def __get__(self, instance, cls): return instance.__dict__[self._name] def __set__(self, instance, value): if self._set_count >= self._set_treshold: raise AttributeError("Can't set attribute '{}'".format(self._name)) else: instance.__dict__[self._name] = value self._set_count += 1 def __delete__(self, instance): raise AttributeError("Can't delete attribute '{}'".format(self._name)) class GenericStrategy(object): portfolio = LockedAttribute("portfolio") def __init__(self, portfolio): self.portfolio = portfolio try: self.portfolio = portfolio except AttributeError as e: print(" ERROR: {}".format(e)) def set_portfolio(self, new_value): self.portfolio = new_value if __name__ == "__main__": strategy = GenericStrategy("some portfolio name") print("Portfolio: {}".format(strategy.portfolio)) try: del strategy.portfolio except AttributeError as e: print(" ERROR: {}".format(e)) try: strategy.set_portfolio("some 2nd portfolio name") except AttributeError as e: print(" ERROR: {}".format(e)) try: strategy.portfolio = "some 3rd portfolio name" except AttributeError as e: print(" ERROR: {}".format(e)) print("Portfolio: {}".format(strategy.portfolio)) 。如今,越来越多的语言倾向于提供一种改变实例结构的方法。

无论如何,有一个所谓的 描述符协议 [Python]: Descriptor HowTo Guide),它是 Python '之一。最强大(也是最容易被误解)的功能。

使用描述符(作为旁注,属性依赖于它们),我写了一段代码(在某种程度上)实现了你的目标要求:

__

备注

  • 我从私有属性的名称(portfolio)中删除了object,以避免在我的代码中使用我正在谈论的修改(会使其更难阅读)< / LI>
  • 对于 Py27 兼容性,类继承try/except。如果兼容性不是强制性的,则可以删除继承关系(默认情况下在 Py3x 中)
  • 我添加了width块来说明行为,在生产中应删除它们
  • 如上所述,如果有人想改变这种行为,可以