Python 类型错误:';类型';对象不可编辑-在对象实例上迭代
我正在做一个项目,我想让我的一门课变得更适合我。就我所知,我可以通过使用元类来做到这一点 首先,我想了解元类是如何工作的。因此,我想提出我自己的实践例子,我做了一个汽车类。所以在这里,我想让我的Car类对象是可移植的,然后我想在main函数中打印它们的名称 代码示例如下所示:Python 类型错误:';类型';对象不可编辑-在对象实例上迭代,python,iterable,Python,Iterable,我正在做一个项目,我想让我的一门课变得更适合我。就我所知,我可以通过使用元类来做到这一点 首先,我想了解元类是如何工作的。因此,我想提出我自己的实践例子,我做了一个汽车类。所以在这里,我想让我的Car类对象是可移植的,然后我想在main函数中打印它们的名称 代码示例如下所示: __author__ = 'mirind4' class IterableCar(type): def __iter__(self): return iter(self.__name__) cl
__author__ = 'mirind4'
class IterableCar(type):
def __iter__(self):
return iter(self.__name__)
class Car(object):
__metaclass__ = IterableCar
def __init__(self, name):
self.name = name
if __name__=='__main__':
car1 = Car('Mercedes')
car2 = Car('Toyota')
for cars in Car:
print (cars.name)
但不幸的是,我遇到了一个打字错误:
TypeError: 'type' object is not iterable
您能告诉我代码中的错误在哪里吗?到目前为止,我已经在这个网站和互联网上检查了类似的问题,但我不知道问题是什么。我正在使用python 3.4。
提前谢谢 据我所知,通过使用元类使类对象可移植效果很好:
from __future__ import print_function
class IterableCar(type):
def __iter__(cls):
return iter(cls.__name__)
class Car(object):
__metaclass__ = IterableCar
def __init__(self, name):
self.name = name
if __name__=='__main__':
car1 = Car('Mercedes')
car2 = Car('Toyota')
for cars in Car:
print (cars)
结果:
mgilson$ python ~/sandbox/test.py
C
a
r
下面是一个我实际跟踪生成的汽车的示例:
from __future__ import print_function
import weakref
class IterableCar(type):
_cars = weakref.WeakSet()
def __iter__(cls):
return iter(cls._cars)
def add_car(cls, car):
cls._cars.add(car)
class Car(object):
__metaclass__ = IterableCar
def __init__(self, name):
self.__class__.add_car(self)
self.name = name
if __name__=='__main__':
car1 = Car('Mercedes')
car2 = Car('Toyota')
for cars in Car:
print (cars.name)
请注意,如果您使用的是python3.x,要使用元类,您需要:
class Car(metaclass=IterableCar):
...
而不是:
class Car(object):
__metaclass__ = IterableCar
这很可能解释了您遇到的问题。要跟踪所创建类的实例,我们将首先为元类创建的每个类添加
\u cars
属性。这将是一组弱引用,因此类本身不会阻止未使用的实例被垃圾收集
class IterableCar(type):
def __new__(meta, name, bases, attrs):
attrs['_cars'] = weaker.WeakSet()
return type.__new__(meta, name, bases, attrs)
要添加实例,我们将覆盖\uuuuu调用
。本质上,这就是您在定义类本身时通常放入的代码的位置
def __call__(cls, *args, **kwargs):
rv = type.__call__(cls, *args, **kwargs)
cls._cars.add(rv)
return rv
并通过迭代实例集使该类可移植
def __iter__(self):
return iter(self._cars)
任何使用IterableCar的类都将自动跟踪其实例
class Car(metaclass=IterableCar):
def __init__(self, name):
self.name = name
car1 = Car('Mercedes')
car2 = Car('Toyota')
for cars in Car:
print(cars.name)
对于车内的车辆,您有
。汽车是一种阶级定义。你期望它做什么?你的意思是把car1
和car2
放在一个列表中,然后重复这个列表吗?(我知道你的问题的顶部有一些关于“使一个类变得可移植”的东西,但不清楚你想要什么。Car
似乎并不代表任何类型的集合。)@Two-bitalchest——我想OP希望它产生C-a-R
。。。制作一个iterable类是一个有趣的概念…@mgilson实际上我猜OP希望它返回到目前为止创建的每个实例,我怀疑这是可能的,但我们将看到。在Python 3中,您使用类Car(metaclass=IterableCar)
定义一个元类,不使用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu是的,weakref.WeakSet可能是其中最容易使用的对象,在这里可能会有所帮助,但我认为这超出了这个问题的范围。。。(因为我们甚至都不知道OP想要做什么…@DanD。--更新为WeakSet
@DanD。不幸的是,我不明白为什么没有weakref模块的程序会出现内存泄漏问题。垃圾收集器在这种情况下不工作吗?老实说,我对这个话题还是有点初学者,对此我很抱歉。你能给我一个简短的解释吗?(我知道什么是内存泄漏,但我不知道它在mgilson的代码中的位置)。非常感谢@mirind4——如果在类级别保留实例列表,那么每次创建的实例都会有一个引用。因此,引用计数永远不会下降到0,因此对象将永远无法被垃圾收集。这可能是你想要的行为。使用WeakSet
,当一个对象超出范围时,它将被垃圾收集,类将停止跟踪它。现在,如果你只是把它作为修复“内存泄漏”的薄弱环节,那么你就万事大吉了:-)。而且,为了完整起见,我想你还需要添加\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu