2012-03-15 61 views
2

我想創建一個知道不根據輸入參數實例化的類。對於一個簡單的例子,如果我想創建一個對象,只能存在如果其輸入參數中的一個是> 1,則在創建對象時返回除對象之外的東西

foo = new_object(0.1) 

應返回到Nonefoo而不是對象。

它讓我覺得作爲一個優雅的方式來創建對象,因爲這意味着我需要在類外沒有代碼,以決定是否要創建它還是不

有沒有辦法做到這一點,還是同樣有用,就這練習不好,爲什麼?

+7

提高'ValueError'將是Python的解決方案。 – 2012-03-15 14:33:04

+0

引發異常是通常的路線,但不是唯一的路線。還有其他Pythonic解決方案。 – 2012-03-15 14:53:51

+0

但是如果你想要返回關於初始化失敗的具體信息,你能做到這一點,例外 – 2012-03-15 18:06:21

回答

3

你需要重寫__new__ - 確保它採用相同的參數__init__

class Test(object): 
    def __init__(self, value): 
     self.value = value 
    def __new__(cls, value): 
     if value > 1: 
      return object.__new__(cls) 
     return None 
    def __repr__(self): 
     return "Test value %d" % self.value 


t1 = Test(2) 
print repr(t1) 
t2 = Test(1) 
print repr(t2) 

Python支持從__new__返回不同類型的對象,但這是相當罕見的做法。

在您的使用情況,如果你是

foo = Test(value) # will None if value <= 1 

,這是你必須做很多次的東西之間

if value < 1: 
    foo = None 
else: 
    foo = Test(value) 

選擇的話,我肯定會考慮讓該類做它。

在這種情況下,你不擁有控制權new_object你可以使自己的工廠函數:

def maybe_foo(value): 
    if value > 1: 
     return new_object(value) 
    return None 
1

很明顯,這將是一個不好的做法,因爲很簡單的原因,沒有人這樣做。調用構造函數應該構造對象實例,而不是有選擇地決定它是否需要。構建對象時,您不需要檢查失敗。所以它有一個相當高的「wtf配額」,這從來就不是一個好主意。

這就是說,我不確定是否有可能,因爲__init__()已經在實例創建之後運行(並且不以return self結尾)。這是Python,我敢肯定可以發生一些事情。我的觀點是,這樣做是一個壞主意。

+1

「沒有人這樣做」這種做法很罕見,不一定是壞事。 '__init__'是初始化器,只有在__new__(構造函數)返回一個與它所屬類相同的類型時才被調用。 – 2012-03-15 14:37:50

2

您可以覆蓋__new__()以有效地將對象實例化轉換爲類似工廠的操作,就像您想在此處執行的操作一樣。我有時希望使用抽象基類的__new__()作爲具體子類的工廠,只要具體子類的列表可以被限制和已知。只要確保它是你的問題的最佳解決方案,因爲它可能是不...