如何动态组合和访问Python中的类属性?

时间:2010-07-20 00:18:21

标签: python

我有一个Python类,其属性名为:date1,date2,date3等。

在运行时,我有一个变量i,它是一个整数。

我想要做的是根据i的值在运行时访问相应的日期属性。

例如,

如果i == 1,我想访问myobject.date1

如果我= = 2,我想访问myobject.date2

我想为类而不是属性做类似的事情。

例如,我有一堆类:MyClass1,MyClass2,MyClass3等。我有一个变量k。

如果k == 1,我想实例化一个新的MyClass1实例

如果k == 2,我想实例化一个新的MyClass2实例

我该怎么做?

修改

我希望避免使用巨大的if-then-else语句来选择合适的属性/类。

Python中有没有办法使用变量的值动态编写类名?

6 个答案:

答案 0 :(得分:25)

在运行时间之前,如果您不知道其名称,则可以使用getattr()来访问该属性:

obj = myobject()
i = 7
date7 = getattr(obj, 'date%d' % i) # same as obj.date7

如果您将编号的类保留在名为foo的模块中,则可以再次使用getattr()按号码访问它们。

foo.py:
  class Class1: pass
  class Class2: pass
  [ etc ]


bar.py:
  import foo
  i = 3
  someClass = getattr(foo, "Class%d" % i) # Same as someClass = foo.Class3
  obj = someClass() # someClass is a pointer to foo.Class3
  # short version:
  obj = getattr(foo, "Class%d" % i)()

说了这么多,你真的应该避免这种事情,因为除了阅读整个代码库之外,你永远无法找到这些编号属性和类的使用位置。你最好把所有东西放在字典里。

答案 1 :(得分:5)

对于第一种情况,您应该能够:

getattr(myobject, 'date%s' % i)

对于第二种情况,你可以这样做:

myobject = locals()['MyClass%s' % k]()

但是,您首先需要这样做的事实可能表明您正在以非Pythonic的方式解决问题。

答案 2 :(得分:4)

好吧,好吧......看起来这需要一些工作。首先,对于你的约会*事物,它们应该存储为属性的字典。例如,myobj.dates[1],等等。

对于类,听起来好像你想要多态。你的所有MyClass *类都应该有一个共同的祖先。祖先的__new__方法应该确定要对哪个子进行实例化。

父母知道该做什么的一种方法是保持对孩子的谴责。有些方法,父类不需要通过搜索它的所有子类来枚举它的子类,但实现起来有点复杂。有关如何采用该方法的详细信息,请参阅here。特别阅读评论,他们会对其进行扩展。

class Parent(object):
    _children = {
      1: MyClass1,
      2: MyClass2,
    }

    def __new__(k):
        return object.__new__(Parent._children[k])

class MyClass1(Parent):
    def __init__(self):
        self.foo = 1

class MyClass2(Parent):
    def __init__(self):
        self.foo = 2

bar = Parent(1)
print bar.foo # 1
baz = Parent(2)
print bar.foo # 2

第三,你真的应该重新考虑你的变量命名。不要使用数字来枚举变量,而是给它们提供有意义的名称。 ik很难使用,因为它们是按照惯例为循环索引保留的。

现有代码的示例将非常有助于改进它。

答案 3 :(得分:2)

我同意Daenyth的意见,但如果你感觉很挑剔,你可以使用所有课程附带的 dict 方法:

>>> class nullclass(object):
        def nullmethod():
            pass

>>> nullclass.__dict__.keys()
['__dict__', '__module__', '__weakref__', 'nullmethod', '__doc__']

>>> nullclass.__dict__["nullmethod"]
<function nullmethod at 0x013366A8>

答案 4 :(得分:1)

获取所有属性的列表,请尝试:

dir(<class instance>)

答案 5 :(得分:0)

对于第一个例子,我将在类上添加一个实例方法。

def get_date_for_i(self, i):
    if i == 1:
        return self.date1
    elif i == 2:
        return self.date2
    # etc...

对于第二个我会使用工厂功能:

def get_class_for_k(k):
   if k == 1:
       return MyClass1
   if k == 2:
       return MyClass2

   # etc...