How to dynamically compose and access class attributes in 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中,有没有一种方法可以使用变量的值动态地组合类名?
运行时不知道属性名称时,可以使用
1 2 3 | obj = myobject() i = 7 date7 = getattr(obj, 'date%d' % i) # same as obj.date7 |
。
如果将编号类保存在名为
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 | getattr(myobject, 'date%s' % i) |
。
对于第二种情况,您可以执行以下操作:
1 | myobject = locals()['MyClass%s' % k]() |
然而,事实上你首先需要这样做,这可能是一个迹象,表明你正在以一种非常非Python的方式来解决这个问题。
好吧,好吧…这似乎需要一些工作。首先,对于日期*的事情,它们应该存储为属性的dict。例如,
对于这些类,听起来您需要多态性。所有myclass*类都应该有一个共同的祖先。祖先的
父母知道该做什么的一个方法是对孩子们口述。父类有一些方法不需要通过搜索它的所有子类来枚举它的子类,但是实现起来有点复杂。请参阅这里,以了解更多关于您如何采取这种方法的信息。特别是阅读评论,他们会扩展评论。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 |
第三,您真的应该重新考虑变量命名。不要用数字来枚举变量,而是给它们起有意义的名字。
现有代码的一个示例将对改进它非常有帮助。
我同意Daenyth的观点,但是如果你觉得自己很时髦,你可以使用所有类附带的dict方法:
1 2 3 4 5 6 7 8 9 | >>> class nullclass(object): def nullmethod(): pass >>> nullclass.__dict__.keys() ['__dict__', '__module__', '__weakref__', 'nullmethod', '__doc__'] >>> nullclass.__dict__["nullmethod"] <function nullmethod at 0x013366A8> |
。
要获取所有属性的列表,请尝试:
1 | dir(<class instance>) |
。
对于第一个示例,我将在类上添加一个实例方法。
1 2 3 4 5 6 | def get_date_for_i(self, i): if i == 1: return self.date1 elif i == 2: return self.date2 # etc... |
第二步,我将使用工厂功能:
1 2 3 4 5 6 7 | def get_class_for_k(k): if k == 1: return MyClass1 if k == 2: return MyClass2 # etc... |
号