2013-04-24 42 views
1

這可能是一個超級結點的問題,道歉。我試圖在PHP中實現一種效果,我從PHP中獲得了這種效果,PHP正在爲私有屬性構建getter和setter函數。Python 2.7版:如何建立的getter/setter函數訪問類不繼承屬性?

在PHP中我通常會做這樣的事情:

<?php 
class newClass() { 
    private $var = null; 

    function newClass($initVal) { 
     //init 
    } 

    public function get($var) { 
     if (isset($this->$var)) { 
      return $this->$var; 
     } 
    } 
} 
?> 

但是,試圖在Python同樣的想法:

class newClass(): 
    def __init__(self, initVal): 
     self.__nameOfVar1 = initVal 
     self.__nameOfVar2 = initVal 


    def get(self, var): 
       #assuming, when called, var = nameOfVar1 
     if self.__var: 
      return self.__var 

拋出Error AttributeError:'newClass' object has no attribute '__var'

也是理所當然的,它沒有。如何構建getter和setter函數來訪問私有屬性?


UPDATE:

我已經離開了原來的問題,因爲它似乎對新來Python的學習,​​他們可能會不小心將帶來其約定從其他語言了一些有益的。但實際上,我最初的問題有點不同,試圖讓這個問題更籠統,我混淆了我的實際需要。因此,這裏的修正案:

其實我不是用私有屬性的工作;實際上,我正在試圖通過構圖環境向下傳遞屬性。即:

Class A作爲一個屬性,有一個Class B對象不會從Class A繼承。這幾乎是從來沒有的情況下Class B需要從Class A的任何信息,但在我的項目有一個情況,其中,如果用戶選擇不提供信息給Class B,有可能使得最後努力來推斷一個合理的解決方案的聲明,但是它需要來自Class A的信息,通常它不需要。

我可以建立Class B總是有這樣的信息,但這意味着我幾乎總是浪費時間和記憶(儘管它可能是微不足道的)。爲了使這個具體的,想象一下:

toothbrushbristles,並bristles可以提供用戶提供一個最佳的刷牙體驗,打造了一批適合於任何一個「軟」或「公司」刷毛的。但是,如果用戶不提供這一點,那麼我想bristlesbrush它的表面積,使其能夠猜測的平均數應該是什麼。

我想出了這一點,雖然我有直觀的感覺,Python程序員會恨我吧;我只是想明白爲什麼:

@staticmethod 
def request(self, var): 
    appIndex = self.__dict__ 
    if appIndex[var]: 
     return appIndex[var] 

print Class.request(instance, var) 

工程就像一個魅力,但我認爲這是Python的異端。 爲什麼?

+1

在做這件事之前,你應該問自己兩個問題:1)你爲什麼使用私有屬性? 2)你爲什麼使用getter/setter函數?這兩個都不是Pythonic,通常有更好的方法來完成Python中的任務。第三個問題是,不是檢查是否設置了變量,而是應該始終將其初始設置爲某個默認值,然後檢查該變量而不是檢查它是否「已設置」。 – BrenBarn 2013-04-24 19:39:16

+3

不,它不會;這段代碼會拋出一個'SyntaxError',因爲'__init__'沒有'def'。即使在那裏,'__var'也不會拋出一個屬性錯誤,因爲它是像引用一樣的[mangled](http://docs.python.org/2/reference/expressions.html#atom-identifiers)在'__init__'中。 – 2013-04-24 19:39:36

+0

請注意,在python中沒有真正的私有變量...... – 2013-04-24 19:44:05

回答

9

什麼您正在尋找是properties

class Foo(): 
    def __init__(self): 
     self._spam = 0 

    @property 
    def spam(self): 
     print("in the getter: ") 
     return self._spam 

    @spam.setter 
    def spam(self, move): 
     print("in the setter: ") 
     self._spam = move + self._spam 

f = Foo() 
f.spam = 2 
print(f.spam) 

輸出:

in the setter: 
in the getter: 
2 
+0

啊。我懂了。感謝您不只是說我現在正在意識到您應該說的,即「閱讀如何在python中完成面向對象的編程」。非常感謝,哈哈。 – Jonline 2013-04-24 19:40:47

+0

@Jonline:「在Python中如何進行面向對象的編程」是數據屬性是對象接口的一部分。除非絕對必要,否則不要使用getter和setter。當它需要時,使用'@ property'從接口中隱藏getter和setter。如果你從這裏學到的教訓是「我應該通過使用@屬性來爲每個屬性構建getter和setter」,那麼你就是在儘可能做錯事情。 – abarnert 2013-04-24 20:12:12

+0

@abarnert謝謝,這是我非常感謝的那種建議。我做了一個基於私有屬性的例子,因爲它似乎(當時!)更有可能是普遍有用的。實際上,我真正的問題是構建一個函數,允許沒有共享繼承的兄弟類(除了作爲對象)在對象之間請求(在_rare_ occasion上)屬性。你能指出一個你推薦學習Py的OOP約定的資源嗎? – Jonline 2013-04-25 14:49:32

-1

嗯,首先,Python沒有私有變量。你所指的是名稱修改。目的是防止在導入模塊時發生名稱衝突。每當你在一個有兩個ununderscore的類中寫一個變量時,類的名字就會被添加到它的前面。因此,將變量「__var__」命名爲python「private」事物的自定義會更明智。然而,另一方面,在python中,如果你想讓一些變量能夠設置和獲取一個變量,通常只允許直接訪問(與Java或其他語言不同)是最有意義的。

+1

「'__magic__'」名字被保留用於實現(Python實現)。對於「私人」的pythonic命名約定(如「沒有你的擔心,保證無效如果開封」)屬性是'_single_leading_underscore' – 2013-04-24 20:04:37

+0

好吧。我想我沒有在那裏作出區分,但這是一個很好的做法。 – 2013-04-24 23:54:04