2012-05-01 42 views
15

我是相當新的Python和有關於以下類問題:最佳實踐定義實例變量時

class Configuration: 
    def __init__(self): 
     parser = SafeConfigParser() 
     try: 
      if parser.read(CONFIG_FILE) is None: 
       raise IOError('Cannot open configuration file') 
     except IOError, error: 
      sys.exit(error) 
     else: 
      self.__parser = parser 
      self.fileName = CONFIG_FILE 

    def get_section(self): 
     p = self.__parser 
     result = [] 
     for s in p.sections(): 
      result.append('{0}'.format(s)) 
     return result 

    def get_info(self, config_section): 
     p = self.__parser 
     self.section = config_section 
     self.url = p.get(config_section, 'url') 
     self.imgexpr = p.get(config_section, 'imgexpr') 
     self.imgattr1 = p.get(config_section, 'imgattr1') 
     self.imgattr2 = p.get(config_section, 'imgattr2') 
     self.destination = p.get(config_section, 'destination') 
     self.createzip = p.get(config_section, 'createzip') 
     self.pagesnumber = p.get(config_section, 'pagesnumber') 

是否確定到另一個函數在這個例子中添加更多的實例變量,get_info,或在構造函數中定義所有實例變量是否是最佳實踐?如果我在整個地方定義新的實例變量,它不會導致意大利麪條代碼嗎?

編輯:我用這個代碼與一個簡單的圖像刮刀。通過get_section我返回配置文件中的所有部分,然後遍歷它們以訪問我從中刮取圖像的每個站點。對於每次迭代,我撥打get_section以獲取配置文件中每個部分的配置設置。 如果任何人都可以想出另一種方法,它會沒事的!謝謝!

+0

http://stackoverflow.com/questions/2964230/python-how-should-i-make-instance-variables-available –

+0

'自我。應該在__init __()'的開頭設置__parser = None。原因是'__init __()'被稱爲*已經存在的*對象的第一個代碼。如果解析器無法讀取配置文件並引發異常,則該異常可能會被catched elswhere(程序可能不會終止)。然後,Configuration類的對象仍然存在,後面的get_info()會導致* AttributeError:Configuration實例沒有屬性'__parser'。 – pepr

+0

@pepr我應該讀你回答我應該在'__init __。py'的開頭添加'self .__ parser = None'的方式還是建議將解析器初始化從'__init __。py'移動到另一個函數? – happygoat

回答

11

我肯定會在__init__聲明的所有實例變量。不這樣做會導致複雜性增加和潛在的意外副作用。

爲了提供David Hall在訪問方面的替代觀點,來自Google Python style guide

Access Control:

If an accessor function would be trivial you should use public variables instead of accessor functions to avoid the extra cost of function calls in Python. When more functionality is added you can use property to keep the syntax consistent

On the other hand, if access is more complex, or the cost of accessing the variable is significant, you should use function calls (following the Naming guidelines) such as get_foo() and set_foo(). If the past behavior allowed access through a property, do not bind the new accessor functions to the property. Any code still attempting to access the variable by the old method should break visibly so they are made aware of the change in complexity.

From PEP8

For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.

Note 1: Properties only work on new-style classes.

Note 2: Try to keep the functional behavior side-effect free, although side-effects such as caching are generally fine.

Note 3: Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.

Python是不是Java/C#,它有如何能看起來應該和寫很強烈的想法。如果你正在編寫python,讓它的外觀和感覺像python是有意義的。其他人將能夠更容易地理解你的代碼,你也可以更好地理解其他Python代碼。

+1

+1,因爲我確實贊同Python中的「我們都是成年人」哲學。我的主要牛羣是你必須知道的類,調用某個函數才能使課程處於有效狀態。 –

+0

@DavidHall在去年pycon「停止寫作課程」中有一個非常有趣的話題,這裏是黑客新聞主題,它有一些很好的討論。線程和視頻都值得一讀。 http://news.ycombinator.com/item?id=3717715 –

+0

乾杯 - 我會看看。正如你可能會告訴我是一個知道一些python的C++/c#開發人員,所以這樣的討論很好閱讀。 –

5

我希望在構造函數中設置所有實例變量,使其具有類似get_info()的功能,這些功能需要將該類置於有效狀態。

對於只通過調用方法(例如get_info())實例化的公共實例變量,您可以創建一個類,該類是一個可以使用的雷區。

如果您擔心某些配置值並非總是需要而且計算起來很昂貴(我想這就是爲什麼您有get_info(),允許延遲執行),那麼我會考慮重構該子集將其配置爲第二類,或者引入properties或返回值的函數。

通過屬性或獲取樣式函數,您鼓勵該類的消費者通過定義的接口並改進封裝。

一旦你有了實例變量的封裝,你可以選擇做一些事情,而不僅僅是拋出一個異常 - 你可以自己調用get_info(),或者拋出一個自定義的異常。


1.不能提供100%的封裝與Python,因爲一家領先的雙下劃線表示私有的實例變量是唯一的民營按照慣例

+0

我沒有看到與公共實例變量相比屬性的好處。你可以簡單地把所有東西都變成一個公共實例變量,如果你以後需要它來執行一些其他的操作而不是設置/獲取一個值,那麼你總是可以將它轉換爲一個屬性。 – interjay

+0

好點 - 我的公共實例變量的主要問題是在函數中實例化它們,比如get_info讓不必要的難於使用的類。但是你和安德魯巴雷特已經讓我感動地編輯了我的答案,強調了構造函數。 –