Python“受保护”属性

时间:2009-04-28 12:55:51

标签: python

如何从子类访问父类的私有属性(不公开)?

7 个答案:

答案 0 :(得分:81)

我对Python约定的理解是

  • _member受保护
  • __成员是私人的

如果您控制父类的选项

  • 使其受保护而非私密 因为这看起来像你真的 想
  • 使用getter(@property def _protected_access_to_member ...)限制受保护的访问

如果你不控制它

  • 撤消名称修改。如果你 dir(对象)你会看到名字 像_Class__member这样的东西 Python对领导__做了什么 “让它变得私密”。没有 在python中真正私密。这可能被认为是邪恶的。

答案 1 :(得分:39)

两种保护哲学

一些语言设计者订阅了以下假设:

  

“许多程序员都是不负责任的,愚蠢的,或两者兼而有之。”

这些语言设计人员会感到很想通过在他们的语言中引入private说明符来保护程序员。 不久之后,他们意识到这通常太不灵活,并且也会引入protected

相比之下,像Python的Guido van Rossum这样的语言设计师认为程序员是负责任的成年人并且能够做出良好的判断(可能不总是,但通常)。 他们发现,如果有需要,每个人都应该能够访问程序的元素,这样语言就不会妨碍做正确的事情。 (能够可靠地妨碍错误的事物的唯一编程语言是NULL语言)

因此,Python中的_myfield意味着“这个模块的设计者正在使用这个属性做一些非显而易见的事情,所以请不要修改它,如果可以的话,不要读它甚至 - 已经提供了获取相关信息的合适方式(或者我们希望如此)。“

如果您无法远离访问_myfield(例如在子类中的特殊情况下),您只需访问它。

答案 2 :(得分:15)

使用@property@name.setter执行您想要的操作

e.g

class Stock(object):

    def __init__(self, stockName):

        # '_' is just a convention and does nothing
        self.__stockName  = stockName   # private now


    @property # when you do Stock.name, it will call this function
    def name(self):
        return self.__stockName

    @name.setter # when you do Stock.name = x, it will call this function
    def name(self, name):
        self.__stockName = name

if __name__ == "__main__":
      myStock = Stock("stock111")

      myStock.__stockName  # It is private. You can't access it.

      #Now you can myStock.name
      N = float(raw_input("input to your stock: " + str(myStock.name)+" ? "))

答案 3 :(得分:2)

如果变量名称为“__secret”且类名为“MyClass”,则可以在名为“var”的实例上以这样的方式访问它

var._MyClass__secret

建议/模仿保护的惯例是使用前导下划线命名:self._protected_variable = 10

当然,如果真的需要,任何人都可以修改它。

答案 4 :(得分:2)

似乎没有人回答原来的问题

  

如何从子类

访问父类的私有属性

所以这是一个简单的用例,演示了两个选项 - 访问父类__private variables和使用@property decorator

class Family:

    def __init__(self, name):
        self.__family_name = name

    @property
    def name(self):
        return self.__family_name


class Child(Family):

    def __init__(self, first_name, last_name):
        super(Child, self).__init__(last_name)
        self.__child_name = first_name


    @property
    def name(self):
        return (self.__child_name, super(Child, self).name)


if __name__ == '__main__':
    my_child = Child("Albert", "Einstein")

    # print (my_child.__child_name)         # AttributeError - trying to access private attribute '__child_name'
    # print (my_child.__family_name)        # AttributeError - trying to access private attribute '__family_name'
    print (my_child._Child__child_name)     # Prints "Albert" - By accessing __child_name of Child sub-class
    print (my_child._Family__family_name)   # Prints "Einstein" - By accessing __family_name in Family super-class
    print (" ".join(my_child.name))         # Prints "Albert Einstein" - By using @property decorators in Child and Family 

答案 5 :(得分:0)

制作一个存取方法,除非我遗漏了一些东西:

def get_private_attrib(self):
  return self.__privateWhatever

答案 6 :(得分:0)

我认为这段代码比史蒂夫更清楚一些。史蒂夫的回答对我想做的事情最有帮助,谢谢!我用python 2.7和python 3.6进行了测试。

<form id="login" action="http://example.com/login/index.php" method="post">
  <div class="loginform">
    <div class="form-label"><label for="username">Username</label></div>
    <div class="form-input">
      <input name="username" id="username" type="text" size="15" value="">
    </div>
    <div class="clearer">
      <!-- -->
    </div>
    <div class="form-label"><label for="password">Password</label></div>
    <div class="form-input">
      <input name="password" id="password" type="password" size="15" value="">
    </div>
  </div>
  <div class="clearer">
    <!-- -->
  </div>
  <div class="rememberpass">
    <input name="rememberusername" id="rememberusername" type="checkbox" value="1">
    <label for="rememberusername">Remember username</label>
  </div>
  <div class="clearer">
    <!-- -->
  </div>
  <input id="loginbtn" type="submit" value="Log in">
  <div class="forgetpass"><a href="forgot_password.php">Forgotten your username or password?</a></div>
</form>