2013-01-15 168 views
2

我有它針對每個類別的不同名稱的範疇類,該類別的名稱可以是未知的,有好有壞,所有類別共享相同的行爲,所以我不希望創建創建對象

Category.GOOD 

這個語句應該返回一個類的對象與他的名字爲「好」,所以我嘗試:子類爲每種類型的類別中,有問題,當我試圖 以這種方式創造不同的類別來 如下:

class Category(object):                            

    def __init__(self, name):                          
     self.name = name                           

    @property 
    def GOOD(self): 
     category = Category(name='good')                       
     return category                            

    @property 
    def BAD(self): 
     category = Category(name='bad')                        
     return category 

然後,我創建並使用類有以下的輸出:

c = Category.GOOD 
c.name 
AttributeError: 'property' object has no attribute 'name' 

意識到這不工作我試着一個java一樣的做法:

class Category(object):                           

    GOOD = Category(name='good') 
    BAD = Category(name='bad')                         

    def __init__(self, name): 
     self.name = name 

我來到這裏是一個未定義的名稱「類別」的錯誤,所以我的問題是如果有一種pythonic的方式來創建類似這樣的對象。

+0

你不能做到這一點外的開箱即用的了'property';您必須創建自己的描述符,或者只需使用'classmethod'並調用GOOD()',如下所示。 –

+0

@MartijnPieters - 不可能用這種行爲創建描述符嗎?問題在於他正在訪問類中的描述符(這只是一個屬性,沒有任何特殊描述符的魔術出現) – mgilson

+0

@mgilson:類也調用描述符; 'classmethod'也是一個描述符。 'function .__ get __(None,cls)'在Python 2中給出了一個'unbound method'(在Python 3中返回'self'),所以它肯定會被調用! –

回答

1

我會使用模塊變量此。想想你有模塊category.py

class Category(object): 
    # stuff... 

現在你把兩個全局對象是:

GOOD = Category(name='good') 
BAD = Category(name='bad') 

您可以使用它像:

from path.to.category import GOOD, BAD 

我就不多說了這是Python的但我認爲這種做法是優雅的。

2

你可能想使用classmethods:

class Category(object): 

    @classmethod 
    def GOOD(cls): 
     category = cls(name='GOOD') 
     return category 

現在你可以做。

0

,你不能使用類定義本身內部類定義要點。所以最直接的方式來實現你想要的是使用類/靜態方法,如下圖所示,甚至包裝的常量。

class Category(object): 
    def __init__(self, name): 
     self.name = name 

    @classmethod 
    def GOOD(cls): 
     return Category(name='good') 

    @classmethod 
    def BAD(cls): 
     return Category(name='bad') 

print Category.GOOD().name 

class Category(object): 
    def __init__(self, name): 
     self.name = name 

    @staticmethod 
    def GOOD(): 
     return Category(name='good') 

    @staticmethod 
    def BAD(): 
     return Category(name='bad') 

print Category.GOOD().name 
+0

你測試過了嗎?你需要*在這裏打電話* GOOD ... – mgilson

+0

你是對的 - 只是複製測試其他想法的代碼。固定。謝謝。 – Vladimir

+0

作爲一個方面說明,我不喜歡在所有大寫字母上寫'GOOD'。它看起來太像是在大喊大叫......無論如何,現在看起來是正確的:) – mgilson

2

你不能用一個屬性做到這一點;你要麼必須使用classmethod,或創建你自己的descriptor

class classproperty(property): 
    def __get__(self, inst, cls): 
     return self.fget(cls) 

我在這裏濫用property裝飾;它實現__set____del__爲好,但我們可以忽略那些在這裏爲方便起見。

然後使用,而不是property

class Category(object): 
    def __init__(self, name): 
     self.name = name 

    @classproperty 
    def GOOD(cls): 
     return cls(name='good') 

    @classproperty 
    def BAD(cls): 
     return cls(name='bad') 

現在訪問Category.GOOD作品:

>>> Category.GOOD 
<__main__.Category object at 0x10f49df50> 
>>> Category.GOOD.name 
'good' 
+0

Upvoted。在後視中,似乎很清楚,描述符需要在類(而不僅僅是實例)上工作,以便使'classmethod'或'staticmethod'工作。自從幾個月前我教過自己的描述符以來,我認爲自己對這些事情有錯誤的想法...... – mgilson