As far as I can tell, making a class object iterable by using a metaclass works just fine:
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)
Results in:
mgilson$ python ~/sandbox/test.py
C
a
r
Here's an example where I actually track the cars generated:
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)
Note that if you're using python3.x, to use a metaclass you do:
class Car(metaclass=IterableCar):
...
Rather than:
class Car(object):
__metaclass__ = IterableCar
which likely explains the problem that you're experiencing.
Answer from mgilson on Stack Overflowpython - TypeError: 'type' object is not iterable - Iterating over object instances - Stack Overflow
python - TypeError: 'type' object is not iterable in a for loop - Stack Overflow
"'Int' Object is not iterable" Can someone explain what I'm doing wrong?
python saying object is not iterable
What is Python TypeError and what causes it?
How do I quickly debug a Python TypeError?
Should I catch TypeError or let it propagate?
Can somebody help me fix the problem...I get the above error when I run the following chunk of code:
# Returns true if number is wholly divisible by divisor with no remainder.
def isDivisible(number, divisor):
return number % divisor == 0
def sequence(N):
#results = [item for item in range(1, N+1)]
results = []
for i in range(1, N+1):
results.append(i)
return type(results)
def HorseDuckProblem(sequence):
for item in sequence:
if isDivisible(item, 30):
sequence[item] = "HorseDuck"
elif isDivisible(item, 5):
sequence[item] = "Horse"
elif isDivisible(item, 6):
sequence[item] = 'Duck'
else:
sequence[item] = str(item)
return sequence
if __name__ == "__main__":
seq = sequence(100)
print(HorseDuckProblem(seq))
As far as I can tell, making a class object iterable by using a metaclass works just fine:
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)
Results in:
mgilson$ python ~/sandbox/test.py
C
a
r
Here's an example where I actually track the cars generated:
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)
Note that if you're using python3.x, to use a metaclass you do:
class Car(metaclass=IterableCar):
...
Rather than:
class Car(object):
__metaclass__ = IterableCar
which likely explains the problem that you're experiencing.
To track instances of the class that are created, we'll start by adding a _cars attribute to each the class created by the metaclass. This will be set of weak references, so that the class itself does not prevent unused instances from being garbage-collected.
class IterableCar(type):
def __new__(meta, name, bases, attrs):
attrs['_cars'] = weaker.WeakSet()
return type.__new__(meta, name, bases, attrs)
To add the instances, we'll override __call__. Essentially, this is where you put code that you would ordinarily put in __new__ or __init__ when defining the class itself.
def __call__(cls, *args, **kwargs):
rv = type.__call__(cls, *args, **kwargs)
cls._cars.add(rv)
return rv
And to make the class iterable by iterating over its set of instances,
def __iter__(self):
return iter(self._cars)
Any class using IterableCar will automatically track its instances.
class Car(metaclass=IterableCar):
def __init__(self, name):
self.name = name
car1 = Car('Mercedes')
car2 = Car('Toyota')
for cars in Car:
print(cars.name)
You have to specify the range value with range(stop)or range(start, stop[, step]). Maybe range(len(value)) if value is a list.
You get the exception TypeError: 'type' object is not iterable because you are referencing the class range instead of calling it.
You need a start and an end point for the FOR loop.
eg. this will return "This is printed" 10 times.
for i in range(0,9):
print("This is printed")