Your existing function will work provided you assign the next_color
attribute to an
instance of Axes
rather than the class itself.
First of all, with
set_color_sequence
you are basically implementing a
generator in a roundabout way. To
simplify things, we can achieve the same thing in one line using
itertools.cycle
:
from itertools import cycle
...
axes_instance.next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y']).next
In fact, this is the way that matplotlib keeps track of where it is in the color
cycle. For example, if you take a look at an instance of
matplotlib.axes._subplots.AxesSubplot
you will see that it has the attribute
_get_lines.color_cycle
, which is an itertools.cycle
(try calling
color_cycle.next()
).
Now take a look at these two examples:
class MyClass1(object):
# next_color is an attribute of the *class itself*
next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y']).next
class MyClass2(object):
def __init__(self):
# next_color is an attribute of *this instance* of the class
self.next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y']).next
In the first case, what happens is that the assignment
next_color = cycle(['r', 'g', 'b', 'c', 'm', 'y]).next
gets evaluated once and only once, when the class is first imported. This means
that whenever you create a new instance of MyClass1
, its next_color
attribute will point at the exact same itertools.cycle
instance, and
therefore all instances of MyClass1
will share a common state:
a = MyClass1()
b = MyClass1()
print a.next_color is b.next_color
# True
print a.next_color(), a.next_color(), b.next_color()
# r g b
However, the __init__
method gets called again and again whenever a new
instance of the class is being created. As a consequence, every instance of MyClass2
gets
its own itertools.cycle
, and therefore its own state:
a = MyClass2()
b = MyClass2()
print a.next_color is b.next_color
# False
print a.next_color(), a.next_color(), b.next_color()
# r g r
If your goal is to subclass plt.Axes
, you need to put your assignment
somewhere where it will get called by each new instance of your subclass
(probably in __init__
). However, if you just want to add this
method to an existing instance then literally all you need to do is:
axes_instance.next_color = get_color_sequence()