Python:显示在类代码中分配给类对象的属性

时间:2013-03-03 18:46:23

标签: python

我的一个类对一组对象进行了大量的聚合计算,然后分配了一个适合特定对象的属性和值:I.e。

class Team(object):
    def __init__(self, name): # updated for typo in code, added self
        self.name = name

class LeagueDetails(object):
    def __init__(self): # added for clarity, corrected another typo
        self.team_list = [Team('name'), ...]
        self.calculate_league_standings() # added for clarity


    def calculate_league_standings(self):
        # calculate standings as a team_place_dict
        for team in self.team_list:
            team.place = team_place_dict[team.name] # a new team attribute

我知道,只要calculate_league_standings已经投放,每个团队都有team.place。我希望能够做的是扫描class Team(object)的代码并读取所有属性,这些属性既可以通过类方法创建,也可以通过对类对象进行操作的外部方法创建。我有点不耐烦地输入for p in dir(team): print p只是为了查看属性名称是什么。我可以在团队attributes中定义一堆空白__init__。 E.g。

class Team(object):
    def __init__(self, name): # updated for typo in code, added self
        self.name = name
        self.place = None # dummy attribute, but recognizable when the code is scanned

calculate_league_standings返回team._place然后添加

似乎是多余的
@property
def place(self): return self._place

我知道我可以在顶部class Team评论一个属性列表,这是显而易见的解决方案,但我觉得这里必须有一个最佳实践,这里有一些pythonic和优雅。

2 个答案:

答案 0 :(得分:1)

由于Python的动态特性,我不相信你的问题有一个通用的答案。可以通过多种方式设置实例的属性,包括纯分配setattr()和写入__dict__。编写一个工具来静态分析Python代码并通过分析所有这些方法正确地确定类的所有可能属性将非常困难。

在您的特定情况下,作为程序员,您知道class Team在许多实例中将具有place属性,因此您可以决定显式并编写其构造函数,如下所示:

class Team(object):
def __init__(name ,place=None):
    self.name = name
    self.place = place

我想说没有必要定义一个简单属性的属性,除非你想在读或写时发生副作用或派生。

答案 1 :(得分:1)

如果我一半了解您的问题,您希望跟踪初始化后添加了实例的哪些属性。如果是这种情况,您可以使用以下内容:

#! /usr/bin/python3.2

def trackable (cls):
    cls._tracked = {}

    oSetter = cls.__setattr__
    def setter (self, k, v):
        try: self.initialized
        except: return oSetter (self, k, v)
        try: self.k
        except:
            if not self in self.__class__._tracked:
                self.__class__._tracked [self] = []
            self.__class__._tracked [self].append (k)
        return oSetter (self, k, v)
    cls.__setattr__ = setter

    oInit = cls.__init__
    def init (self, *args, **kwargs):
        o = oInit (self, *args, **kwargs)
        self.initialized = 42
        return o
    cls.__init__ = init

    oGetter = cls.__getattribute__
    def getter (self, k):
        if k == 'tracked': return self.__class__._tracked [self]
        return oGetter (self, k)
    cls.__getattribute__ = getter

    return cls

@trackable
class Team:
    def __init__ (self, name, region):
        self.name = name
        self.region = region

#set name and region during initialization
t = Team ('A', 'EU')

#set rank and ELO outside (hence trackable)
#in your "aggregate" functions
t.rank = 4 # a new team attribute
t.ELO = 14 # a new team attribute

#see witch attributes have been created after initialization
print (t.tracked)

如果我不明白这个问题,请指明我错了哪一部分。