2010-09-16 47 views
7

從教程:「類定義是一個可執行語句。」有條件的類創建(Python)

以下是腳本中推薦的內容嗎?

my_switch = False 
if my_switch: 
    class Hello: 
     def __init__(self): 
      self.greeting = "Hello!" 

else: 
    class Hello: 
     def __init__(self): 
      self.greeting = "Salut!" 
+0

對不起,我的意思是問是否建議練習。問題已更新。 – ash 2010-09-16 18:07:30

+1

對於更復雜的情況,推薦的做法是[metaclasses](http://www.ibm.com/developerworks/linux/library/l-pymeta.html),所以你不要重複自己。 – 2010-09-16 18:11:53

+1

順便說一句,對於本地化的具體情況,我會推薦標準庫中的'gettext'模塊。使用它,你的例子可以由一個具有self.greeting = _(「Hello」)的類來處理。 – martineau 2010-09-16 20:07:34

回答

9

你甚至可以做

class Hello: 
    def __init__(self): 
     self.greeting = "Hello!" 

class Salut: 
    def __init__(self): 
     self.greeting = "Salut!" 

if my_switch: 
    Hello = Salut 

(請注意,您的代碼需要小寫類關鍵字...)

+0

謝謝,更新我的代碼。這是一個非常酷的事情 – ash 2010-09-16 18:09:47

+0

-1 @Jasie這是錯誤的三個原因1)爲什麼要定義一個類,如果你不打算使用它?2)就像你最初的那樣,很明顯標識符「Hello」可以指向兩個不同的類對象之一__at創建時間___。現在,我需要閱讀3)任何使用'my_switch == True'完成的調試都會輸出'Salut'作爲類名,這會讓其他人感到困惑 – aaronasterling 2010-09-16 22:10:43

+0

我的意思是說作爲一個例子,證明在P中類也是第一類對象ython,而不是一個實際的代碼來使用。當然,對於像翻譯這樣的東西,你會使用gettext或類似的東西。 – 2010-09-17 16:12:14

5

是的,代碼是有效的。但爲什麼不只是運行代碼來找出?

你也可以用函數定義來做到這一點。

+1

你的第一個陳述有點可疑。如果你總體上採用這種方法,你會發現,例如,在C語言中,負向移位通常會做一些可能有用的事情,但如果你改爲閱讀C手冊,你會發現語言實際上並不支持這一點。 我同意'嘗試它並看到'在python中非常有用,但我可以肯定地看到值問的問題,「這似乎工作,但它是*推薦*嗎?它可能會在未來版本的python中失敗,或在其他平臺上?或導致其他問題?在這種情況下答案是否定的,但仍然。 – greggo 2012-04-26 13:47:24

3

這是有效的代碼,但該格式並不推薦(假設代碼會遵循類聲明)。因爲你最終會使用這個類。假設你仍然使用兩個相同的類,它可能會在之後引起混淆。也許你應該用一個函數包裝代碼來返回你創建的類。現在你有一個基本的factory

def HelloFactory(my_switch) 
    if my_switch: 
     class Hello: 
      def __init__(self): 
       self.greeting = "Hello!" 
    else: 
     class Hello: 
      def __init__(self): 
       self.greeting = "Salut!" 
    return Hello 

helloClass = HelloFactory(False) 
hello = helloClass() 
hello.greeting 

會輸出「Salut!」

+0

我覺得這個片段比OP的片段更加複雜。如果可能的話,我相信應該避免使用嵌套的類/函數,因爲它確實降低了代碼的可讀性。 – MatToufoutu 2010-09-16 21:41:47

+0

@MatToufoutu它不是一個替代品,而是一個簡單的例子,你可以創建工廠方法。我同意爲了添加代碼而添加代碼將創建代碼可讀性。 – Rod 2010-09-20 18:12:13

4

當然不推薦用於本地化,就像你的例子。

要考慮的主要問題是有多少代碼將在類的專用版本中與類似的不同。如果只有少量代碼不同,或者只有數據不同(「你好」與「Salut」),那麼有更好的方法。

我可能會考慮類的條件聲明的一種情況是,如果我在兩個不同的操作系統上提供功能,並且在兩者之間獲得該功能是非常不同的。作爲一個例子,也許我試圖從腳本中驅動iTunes,而在MacOS上,我使用AppleScript來驅動它,但在Windows上我必須使用COM。我可能創建一個包裝類,其餘的代碼可以使用,而不必關心使用哪個操作系統。

+1

即使在你的操作系統的情況下,我也不會這樣做。我有一個父類是'abc'。孩子們將是操作系統特定的。父母的'__new__'將返回相應操作系統特定類型的對象。 – Daenyth 2010-09-16 23:03:10

0

您可能不需要重複執行代碼。問問自己,你是否需要重複類構造代碼,或只是類中的變量?如果是後者,那麼你可以使用這兩種情況下,同一類中__init__()使用的參數,然後有條件地與所需的變量返回的類的實例:

my_switch = False 

class Hello: 
    def __init__(self, greeting): 
     self.greeting = greeting 

if my_switch: 
    mygreeting = "Hello!" 
else: 
    mygreeting = "Salut!" 

hello = Hello(mygreeting) 
print hello.greeting 
# => Salut! 
4

你也可以把周圍的條件「聲明」之類的內部,因爲這些都作爲類結構的一部分執行:

class Hello: 
    if my_switch: 
     igreeting = "Hello!" 
    else: 
     igreeting = "Salut!"  
    def __init__(self, greeting): 
      self.greeting = self.igreeting 

(這裏igreeting是一個類變量,問候一個成員變量)

或只是簡單

class Hello: 
    if my_switch: 
     greeting = "Hello!" 
    else: 
     greeting = "Salut!"  

...通常會產生相同的效果。

5

如果你更喜歡它,你可以把每個類的定義放在一個單獨的.py文件中,並且只需要import即可。像下面這樣:

if my_switch: 
    from hello_en import Hello 
else: 
    from hello_fr import Hello 

h = Hello()