2013-01-15 128 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