Iterate over object attributes in python
我有一个具有几个属性和方法的python对象。我想迭代对象属性。
1 2 3 4 5 6 7 | class my_python_obj(object): attr1='a' attr2='b' attr3='c' def method1(self, etc, etc): #Statements |
我希望生成一个包含所有对象属性及其当前值的字典,但我希望以动态方式进行(因此,如果以后添加另一个属性,我也不必记住更新我的函数)。
在PHP中,变量可以用作键,但python中的对象是不可脚本化的,如果为此使用点表示法,它将创建一个新的属性,其名称为my var,这不是我的意图。
只是为了让事情更清楚:
1 2 3 4 5 6 7 | def to_dict(self): '''this is what I already have''' d={} d["attr1"]= self.attr1 d["attr2"]= self.attr2 d["attr3"]= self.attr3 return d |
·
1 2 3 4 5 6 | def to_dict(self): '''this is what I want to do''' d={} for v in my_python_obj.attributes: d[v] = self.v return d |
更新:对于属性,我的意思是只有这个对象的变量,而不是方法。
假设你有一个类,比如
1 2 3 4 5 6 7 | >>> class Cls(object): ... foo = 1 ... bar = 'hello' ... def func(self): ... return 'call me' ... >>> obj = Cls() |
在对象上调用
1 2 | >>> dir(obj) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo', 'func'] |
您总是可以使用列表理解来筛选出特殊的方法。
1 2 | >>> [a for a in dir(obj) if not a.startswith('__')] ['bar', 'foo', 'func'] |
或者如果你喜欢地图/过滤器。
1 2 | >>> filter(lambda a: not a.startswith('__'), dir(obj)) ['bar', 'foo', 'func'] |
如果要筛选出这些方法,可以使用内置的
1 2 | >>> [a for a in dir(obj) if not a.startswith('__') and not callable(getattr(obj,a))] ['bar', 'foo'] |
您还可以使用检查类与其父类之间的差异。
1 2 | >>> set(dir(Cls)) - set(dir(object)) set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__']) |
通常,在类中放入一个
1 2 3 4 | class IterMixin(object): def __iter__(self): for attr, value in self.__dict__.iteritems(): yield attr, value |
你们班:
1 2 3 4 5 6 7 | >>> class YourClass(IterMixin): pass ... >>> yc = YourClass() >>> yc.one = range(15) >>> yc.two = 'test' >>> dict(yc) {'one': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 'two': 'test'} |
python中的对象将其属性(包括函数)存储在名为
然而,需要对变量名做任何事情通常是不好的设计。为什么不把它们收藏起来呢?
1 2 3 | class Foo(object): def __init__(self, **values): self.special_values = values |
然后可以使用
正如已经在一些答案/注释中提到的,python对象已经存储了其属性的字典(不包括方法)。这可以作为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class A(): def __init__(self, x=3, y=2, z=5): self.x = x self._y = y self.__z__ = z def f(self): pass a = A() print(vars(a)) # {'x': 3, '_y': 2, '__z__': 5} # all of the attributes of `a` but no methods! # note how the dictionary is always up-to-date a.x = 10 print(vars(a)) # {'x': 10, '_y': 2, '__z__': 5} # modifying the dictionary modifies the instance attribute vars(a)["_y"] = 20 print(vars(a)) # {'x': 10, '_y': 20, '__z__': 5} |
使用
(使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class someclass: x=1 y=2 z=3 def __init__(self): self.current_idx = 0 self.items = ["x","y","z"] def next(self): if self.current_idx < len(self.items): self.current_idx += 1 k = self.items[self.current_idx-1] return (k,getattr(self,k)) else: raise StopIteration def __iter__(self): return self |
那就称之为无可辩驳
1 2 3 | s=someclass() for k,v in s: print k,"=",v |
对此的正确答案是您不应该这样做。如果您想要这种类型的东西,要么使用dict,要么您需要显式地向某个容器添加属性。你可以通过学习装饰师来实现自动化。
顺便说一句,在您的示例中,method1和属性一样好。
对于Python 3.6
1 2 3 4 5 6 7 8 9 | class SomeClass: def attr_list(self, should_print=False): items = self.__dict__.items() if should_print: [print(f"attribute: {k} value: {v}") for k, v in items] return items |
对于Python 3.6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class SomeClass: def attr_list1(self, should_print=False): for k in self.__dict__.keys(): v = self.__dict__.__getitem__(k) if should_print: print(f"attr: {k} value: {v}") def attr_list(self, should_print=False): b = [(k, v) for k, v in self.__dict__.items()] if should_print: [print(f"attr: {a[0]} value: {a[1]}") for a in b] return b |