3

我可以看到实现这项工作的多个障碍,这很可能是不可能的,但我想我至少会问......

因此,毫不奇怪,我有一个类AbstractEnumeratedConstantsGroup,当子类化创建一个表示一组枚举常量的对象(例如,返回FLAVORS('VANILLA', 'CHOCOLATE', 'STRAWBERRY')FLAVORS[0]返回值'VANILLA'FLAVORS[1]返回值'CHOCOLATE'FLAVORS.VANILLA返回值等)时0,它使用元类和其他一些步法,以便所有这些都是创建新常量组所需的是:FLAVORS.CHOCOLATE1

class FLAVORS(AbstractEnumeratedConstantsGroup):
    _constants = ('VANILLA', 'CHOCOLATE', 'STRAWBERRY')
FLAVORS = FLAVORS()

我想进一步减少它:

@enumerated_constants_group
FLAVORS = ('VANILLA', 'CHOCOLATE', 'STRAWBERRY')

我不知道如何解决的问题是:

    1. 没有很好的方法从装饰器代码的定义范围中获取对象的标签名称 2. 不能装饰不是类、方法或函数的东西

我考虑过使用工厂/构建器,但我不喜欢的是它需要在代码中重复组名,或者组具有无用的__name__值(用于__repr____str__)。前任:

FLAVOR = enumerated_constants_group('FLAVOR', ('VANILLA', 'CHOCOLATE', 'STRAWBERRY'))

或者

FLAVOR = enumerated_constants_group(('VANILLA', 'CHOCOLATE', 'STRAWBERRY'))
# FLAVOR.__name__ becomes some unfriendly machine-generated string

作为装饰器思想的替代方案,是否可以从工厂方法引用调用范围(通过自省或隐式传递给函数),以便调用该方法会将新创建的对象插入到调用命名空间中给定的名字?前任:

enumerated_constants_group('FLAVOR', ('VANILLA', 'CHOCOLATE', 'STRAWBERRY'))
# I could now reference FLAVOR in any arbitrary scope that the method was called from

我能做些什么来实现我想要的吗?还有其他我没有想到的方法吗?

4

5 回答 5

3

FLAVORS = ('VANILLA', 'CHOCOLATE', 'STRAWBERRY')当您分配给一个裸名(如 中)时,没有一般的方法可以影响发生的事情。所以你想要的是不可能的。

也就是说,您可以编写一个元类,将返回的类替换为自身的实例,这样您就不需要FLAVORS = FLAVORS(...)在第一个示例中使用最后一行。类定义本身就足以创建对象。

于 2012-08-02T18:43:47.460 回答
2

你看过http://code.activestate.com/recipes/413486/

它允许您编写如下代码:

>>> from enum import enum
>>> FLAVORS = enum('VANILLA', 'CHOCOLATE', 'STRAWBERRY')
>>> print FLAVORS
enum (VANILLA, CHOCOLATE, STRAWBERRY)
>>> print FLAVORS.VANILLA
VANILLA
>>> f = FLAVORS.CHOCOLATE
>>> f in FLAVORS
True
>>> for f in FLAVORS:
...     print f
...
VANILLA
CHOCOLATE
STRAWBERRY
于 2012-08-02T18:53:08.833 回答
0

作为中间步骤,你可以做

FLAVORS = type("FLAVORS",
               (AbstractEnumeratedConstantsGroup,),
               {_constants = ('VANILLA', 'CHOCOLATE', 'STRAWBERRY')})()

这导致了一个假装饰器

def enumerated_constants_group(*args):
    AECG=AbstractEnumeratedConstantsGroup
    t = type(args[0], (AECG,), dict(_constants=args[1:]))
    return t()

FLAVORS = enumerated_constants_group('FLAVORS', 'VANILLA', 'CHOCOLATE', 'STRAWBERRY')
于 2012-08-02T18:44:32.770 回答
0

除了函数/方法装饰器之外,您还有类装饰器(至少它们在 python 2.4 中存在),请参阅http://www.python.org/dev/peps/pep-3129/

无论如何,我不确定这是你需要的。

我会选择将(类型,值)作为参数的工厂类。

请注意:如果您的代码就是这样,并且 AbstractEnumeratedConstantsGroup 没有添加任何功能,那么您为什么不直接使用元组呢?

您可以使用以下内容定义一个 constants.py 模块:

FLAVOURS = ('VANILLA', 'CHOCOLATE', 'STRAWBERRY')
PETS = ('DOG', 'CAT', 'FISH')

然后使用您的代码中的这些元组:

import constants
for pet in constants.PETS:
    print 'I have a ', pet
于 2012-08-02T18:47:39.277 回答
0

命名元组怎么样。http://docs.python.org/library/collections.html#collections.namedtuple

于 2012-08-03T20:33:34.483 回答