【问题标题】:TypeError: 'type' object is not iterable - Iterating over object instancesTypeError:“类型”对象不可迭代 - 迭代对象实例
【发布时间】:2015-11-28 11:49:23
【问题描述】:

我正在做一个项目,我想让我的一个类可迭代。据我所知,我可以通过使用元类来做到这一点。

首先我想了解元类是如何工作的。因此,我想展示我自己的练习示例,我制作了一个汽车课程。所以在这里我想让我的 Car 类对象可迭代,然后我想在主函数中打印它们的名称。

代码示例如下:

__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:

TypeError: 'type' object is not iterable

您能告诉我我的代码哪里出错了吗?到目前为止,我已经在这个网站和互联网上检查了类似的问题,但我不知道问题是什么。我正在使用 python 3.4。 提前致谢!

【问题讨论】:

  • 你有for cars in Car。汽车是一个类定义。你期望它做什么?您的意思是将car1car2 放入一个列表并对其进行迭代吗? (我看到你的问题的顶部有一些关于“使类可迭代”的问题,但不清楚你想要什么。Car 似乎不代表任何类型的集合。)
  • @Two-BitAlchemist -- 我认为 OP 希望它产生 C - A - R ... 制作可迭代 class... 的有趣概念
  • @mgilson 我实际上猜测 OP 希望它返回迄今为止创建的每个实例,我怀疑这是可能的,但我们会看到。
  • 在 Python 3 中,您使用 class Car(metaclass=IterableCar) 定义元类,而不是使用 __metaclass__ 属性。
  • 假设元类提供__new__的定义,我相信是这样。

标签: python iterable


【解决方案1】:

据我所知,使用元类使类对象可迭代就可以了:

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

这可能解释了您遇到的问题。

【讨论】:

  • weakref 模块可用于修复内存泄漏。
  • @DanD。 -- 是的weakref.WeakSet 可能是最容易使用的对象,可以在这里提供帮助,但我认为这超出了这个问题的范围......(因为我们甚至不知道 OP 想要做什么。 ..)
  • @DanD。 -- 更新为WeakSet
  • @DanD。不幸的是,我不明白为什么程序在没有weakref 模块的情况下会出现内存泄漏问题。垃圾收集器在这种情况下不工作吗?老实说,我在这个话题上还是有点初学者,对此感到抱歉。你能不能给我一个简短的解释? (我知道什么是内存泄漏,但我不知道它在 mgilson 的代码中在哪里)。非常感谢!
  • @mirind4 -- 如果你在类级别保留一个实例列表,那么每次创建的每个实例都会有一个引用。因此,引用计数永远不会下降到 0,因此对象将永远无法被垃圾回收。这可能是您想要的行为。使用WeakSet,当一个对象超出范围时,它将被垃圾回收并且类将停止跟踪它。
【解决方案2】:

为了跟踪创建的类的实例,我们首先为元类创建的每个类添加_cars 属性。这将是一组弱引用,因此类本身不会阻止未使用的实例被垃圾收集。

class IterableCar(type):
    def __new__(meta, name, bases, attrs):
        attrs['_cars'] = weaker.WeakSet()
        return type.__new__(meta, name, bases, attrs)

要添加实例,我们将覆盖 __call__。本质上,这是您放置定义类本身时通常会放入 __new____init__ 的代码的地方。

    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)

【讨论】:

  • 不错。现在,如果您只是将其设置为 WeakSet 来修复“内存泄漏”,那么您将一切就绪:-)。
  • 而且,为了完整起见,您还需要添加__iter__(这将迭代返回iter(cls._cars)
  • @chepner 感谢您的详细回答,非常感谢! :)
【解决方案3】:

当装饰器期待一个元组并且我传入一个没有尾随逗号的元素时,我出现了这个错误。

@api_view(["GET"])
@authentication_classes((CustomAuthentication,))
@permission_classes((AdminPermission))
def order_attached_documents_from_order_uuid(request):
    # ...
    return Response(status=status.HTTP_200_OK)

在我将@permission_classes((AdminPermission)) 更改为@permission_classes((AdminPermission,)) 之后,一切都开始正常工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-12
    • 2013-09-01
    • 1970-01-01
    • 2017-08-27
    • 2018-10-10
    • 2021-12-13
    • 2019-02-20
    • 2020-03-27
    相关资源
    最近更新 更多