如何动态构建和访问Python中的类属性?
我有一个Python类,里面有一些属性,名字叫:date1、date2、date3等等。
在程序运行的时候,我有一个变量i,它是一个整数。
我想根据i的值来访问相应的日期属性。
比如说,
如果i等于1,我想访问myobject.date1。
如果i等于2,我想访问myobject.date2。
我还想做类似的事情来处理类,而不是属性。
比如,我有一堆类:MyClass1、MyClass2、MyClass3等等。我还有一个变量k。
如果k等于1,我想创建MyClass1的一个新实例。
如果k等于2,我想创建MyClass2的一个新实例。
我该怎么做呢?
编辑
我希望能避免使用一个很大的if-then-else语句来选择合适的属性或类。
在Python中,有没有办法根据变量的值动态生成类名呢?
5 个回答
好的,看来这个代码需要一些改进。首先,你的日期相关的东西,建议把它们存储为一个属性字典。比如说,可以用 myobj.dates[1]
这样的方式来访问。
关于类的部分,听起来你想要实现多态性。所有的 MyClass* 类应该有一个共同的父类。这个父类的 __new__
方法应该负责决定要实例化哪个子类。
父类知道要创建哪个子类的一种方法是保持一个子类的字典。其实有一些方法可以让父类不需要通过查找所有子类来列举它们,但实现起来会复杂一些。你可以查看 这里,了解更多关于这种方法的信息。特别是评论部分,它们有更详细的解释。
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
第三,你真的应该重新考虑一下你的变量命名。不要用数字来给变量编号,而是给它们起一些有意义的名字。像 i
和 k
这样的名字不太好,因为按照惯例,它们通常用作循环的索引。
如果能提供一段你现有代码的示例,那会对改进它非常有帮助。
对于第一种情况,你可以这样做:
getattr(myobject, 'date%s' % i)
对于第二种情况,你可以这样做:
myobject = locals()['MyClass%s' % k]()
不过,首先需要这样做,可能说明你处理问题的方式有点不符合Python的风格。
你可以使用 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)()
不过,话说回来,你真的应该尽量避免这样做,因为你永远无法知道这些编号的属性和类在哪里被使用,除非你逐行阅读整个代码。把所有东西放在一个字典里会更好。