2014-12-27 29 views
1

我正在尝试将类中的函数组织到组中。我决定使用设置属性值的记录向类中的每个函数添加一个属性。我想要制作一个字典,可能是在调用类时,会将键设置为我设置的属性,并将该值作为方法。下面是代码的样本:在python中构建类方法属性的字典

def orientation(lr): 
    def decorator(f): 
     f.orientation = lr 
     return f 
    return decorator 

def level(lr): 
    def decorator(f): 
     f.level = lr 
     return f 
    return decorator 

class Artwork(object): 
    def __init__(self): 
     self.groups = {} 

    def __call__(self): 
     pass 

    @level('good') 
    @orientation(RIGHT) 
    def build_one(self): 
     return """ some stuff """ 

    @level('bad') 
    @orientation(RIGHT) 
    def build_two(self): 
     return """ some stuff """ 

    @level('bad') 
    @orientation(RIGHT) 
    def build_three(self): 
     return """ some stuff """ 

这将会是巨大的,如果是这样,将返回:

test = Artwork() 
test.groups 
>> {'good': [build_one], 'bad': [build_two, build_three]} 

我试图通过类使用反射来循环和寻找属性与hasattr,但我似乎无法得到它的工作。

更新:

我有另一个类艺术继承艺术品。这是在艺术课,我想从一个“组”中调用一个随机函数。目前我手动设置要使用哪些函数,但我试图通过设置一些功能组来使其更加健壮,我可以根据一些初始条件随机调用这些功能组。

class Art(Artwork, object): 

    """ Here is where instead of setting the available_art manually, 
I will use the dict of groups of art functions. 
i.e. {'bad': [func1, func2], 'good': [func3, func5, func6]} """ 
def __init__(self, text, score): 
    self.text = text 
    self.available_art = [self.build_one, 
          self.build_two, 
          self.build_three, 
          self.build_four] 
    self.score = score 

def _decide_rank(self): 
    total = functools.reduce(operator.add, self.score.values()) 
    passing = self.score.get('passing') 
    percentage = (passing/total) * 100 
    rank = SCORE_MAP[percentage] if percentage in SCORE_MAP else SCORE_MAP[min(SCORE_MAP.keys(), key=lambda k: abs(k-percentage))] 
    return rank 

def _get_longest_line(self, text): 
    lines = text.split('\n') 
    return len(max(lines, key=len)) 

def _build_bubble(self, text, spaces, orientation, length=40): 
    bubble = [] 
    right = True if orientation == 'right' else False 
    lines = self._normalize_text(text, length) 
    bordersize = len(lines[0]) 

    rline = ' ' * spaces + ' ' + '-' * bordersize 
    lline = ' ' + '-' * bordersize 
    plines = rline if right else lline 

    bubble.append(plines) 

    for index, line in enumerate(lines): 
     border = self._get_border(lines, index, spaces, right) 
     bubble.append('%s %s %s' % (border[0], line, border[1])) 

    bubble.append(plines) 

    return '\n'.join(bubble) 

def _normalize_text(self, text, length): 
    lines = textwrap.wrap(text, length) 
    maxlen = len(max(lines, key=len)) 
    return [line.ljust(maxlen) for line in lines] 

def _get_border(self, lines, index, spaces, right): 
    if len(lines) < 2: 
     return [' ' * spaces + '<', '>'] if right else [' ' + '<', '>'] 
    elif index == 0: 
     return [' ' * spaces + '/', '\\'] if right else ['/', '\\'] 
    elif index == len(lines) - 1: 
     return [' ' * spaces + '\\', '/'] if right else ['\\', '/'] 
    else: 
     return [' ' * spaces + '|', '|'] if right else ['|', '|'] 

def _randomizer(self): 
    return random.randrange(0, len(self.available_art)) 

def build(self): 
    pic = self.available_art[self._randomizer()] 
    spaces = self._get_longest_line(pic()) 
    orientation = pic.orientation 
    print self._build_bubble(self.text, spaces, orientation) + pic() 

回答

1

您可以通过使用dir()方法重复,像这样:

Artwork.groups = {} 
for attr in dir(Artwork): 
    try: 
     v = getattr(Artwork, attr).level 
    except AttributeError: 
     pass # level-less 
    else: 
     Artwork.groups.setdefault(v, []).append(attr) 

现在这两种形式的工作,becase的groups设置类级别(你只需要摆脱的self.groups = {}线,因为它隐藏在类级部件):

Artwork.groups 
=> {'bad': ['build_three', 'build_two'], 'good': ['build_one']} 
Artwork().groups 
=> {'bad': ['build_three', 'build_two'], 'good': ['build_one']} 

使用dir比访问更好直接,becaue这也是支持的传承(假设你希望子类继承其超水平)

UPDATE

如果您需要将此应用到多个类别,使其成为一个功能:

def add_groups(cls): 
    cls.groups = {} 
    for attr in dir(cls): 
    try: 
     v = getattr(cls, attr).level 
    except AttributeError: 
     pass # level-less 
    else: 
     cls.groups.setdefault(v, []).append(attr) 

然后应用它:

add_groups(Artwork) 
add_groups(Art) 

或者,如果你愿意,你可以使用类装饰器。

+0

我使用了另一种继承艺术品的艺术品。在Art类中,我从静态构建的列表中调用一个随机函数。我想要做的就是从一组函数中调用一个随机函数,即从“好”开始。这就是为什么我仍然有self.groups = {} – Ptrkcon 2014-12-27 19:55:42

+0

,您不需要在实例级别设置它,您可以使用类级别属性。 – shx2 2014-12-27 20:02:47

+0

我会如何在艺术品类内做到这一点?我试图在Artwork中添加Artwork.groups = {},并且出现Artwork未定义的错误。 – Ptrkcon 2014-12-27 20:10:16

相关问题