2009-04-28 168 views
26

如何從子類訪問父類的私有屬性(不公開)?Python「受保護」屬性

+4

你的意思是保護的還是私人的?您的問題與您的標題不同... – unwind 2009-04-28 13:00:18

+7

由於受保護和私人在Python中沒有多大意義,請提供實際的代碼。 – 2009-04-28 13:10:57

回答

60

我的Python公約的理解是

  • _member保護
  • __member是私人

選項,如果你控制了父類

  • 讓它保護,而不是私人 因爲這似乎是你真的 想
  • 使用的吸氣劑(@property高清 _protected_access_to_member ...),以限制保護訪問

如果不控制它

  • 撤消名字改編。如果你 目錄(對象),你會看到名稱 類似_Class__member這是 Python做什麼來領導__到 「讓它私人」。沒有 在Python中真正私有。這可能被認爲是邪惡的。
0

做一個訪問方法,除非我失去了一些東西:

def get_private_attrib(self): 
    return self.__privateWhatever 
2

如果變量名是「__secret」和類名是「MyClass的」您可以訪問它這樣命名的實例「變種「

var._MyClass__secret

公約建議/模擬保護是一個領先的下劃線將其命名爲:self._protected_variable = 10

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

10

使用@property和做你想做什麼

保護如

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)+" ? ")) 
+5

問題是關於訪問子類中的屬性。 – 2012-05-11 19:20:17

22

兩種哲學

一些語言設計者訂閱以下假設:

「許多程序員都是不負責任,模糊不清的,或者兩者兼而有之。」

這些語言的設計者會覺得動心通過引入private符到他們的語言來保護彼此的程序員。 不久後,他們認識到這通常太不靈活,並且也引入protected。相比之下,像Python的Guido van Rossum這樣的語言設計者認爲程序員是負責任的成年人,並且能夠很好地判斷(可能並不總是,但通常)。 他們發現,如果有必要這樣做,每個人都應該能夠訪問程序的元素,以便語言不會妨礙正確的事情。 (唯一的編程語言,可以順利拿到在做錯誤事情的方式是NULL語言)

因此,_myfield在Python是指像「這個模塊的設計者正在做一些不常見的東西有了這個屬性,所以如果可以的話,請不要修改它,甚至不要閱讀, - 已經提供了訪問相關信息的合適方法。「

如果您無法遠離訪問_myfield(例如在子類中的特殊情況),您只需訪問它即可。

0

似乎沒有人回答原來的問題

如何從子類訪問父類的私有屬性

所以這裏有一個簡單的用例,展示了兩個選擇 - 訪問父類__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 
0

我覺得這個代碼是不是史蒂夫的更清晰一點。史蒂夫的回答對我正在嘗試做的事情最有幫助,所以謝謝!我用python 2.7和python 3.6測試了這個。

#! /usr/bin/python 
# 
# From https://stackoverflow.com/questions/797771/python-protected-attributes 
from __future__ import print_function 
import sys 

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): 
     print("In the getter, __stockName is %s" % self.__stockName, file=sys.stderr) 
     return self.__stockName 

    @name.setter # when you do Stock.name = x, it will call this function 
    def name(self, name): 
     print("In the setter, name is %s will become %s" % (self.__stockName, name), file=sys.stderr) 
     self.__stockName = name 

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

    try: 
     myStock.__stockName # It is private. You can't access it. 
    except AttributeError as a: 
     print("As expect, raised AttributeError", str(a), file=sys.stderr) 
    else: 
     print("myStock.__stockName did did *not* raise an AttributeError exception") 


    #Now you can myStock.name 
    myStock.name = "Murphy" 
    N = float(input("input to your stock: " + str(myStock.name)+" ? ")) 
    print("The value of %s is %s" % (myStock.name, N)) 
相關問題