A Plural Rule Iterator
We'll cover the following...
Now it’s time for the finale. Let’s rewrite the plural rules generator as an iterator.
So this is a class that implements __iter__() and __next__(), so it can be used as an iterator. Then, you instantiate the class and assign it to rules. This happens just once, on import.
iter(f) calls
f.__iter__. next(f) callsf.__next__
Let’s take the class one bite at a time.
① When we instantiate the LazyRules class, open the pattern file but don’t read anything from it. (That comes later.)
② After opening the patterns file, initialize the cache. You’ll use this cache later (in the __next__() method) as you read lines from the pattern file.
Before we continue, let’s take a closer look at rules_filename. It’s not defined within the __iter__() method. In fact, it’s not defined within any method. It’s defined at the class level. It’s a class variable, and although you can access it just like an instance variable (self.rules_filename), it is shared across all instances of the LazyRules class.
① Each instance of the class inherits the rules_filename attribute with the value defined by the class.
② Changing the attribute’s value in one instance does not affect other instances…
③ …nor does it change the class attribute. You can access the class attribute (as opposed to an individual instance’s attribute) by using the special __class__ attribute to access the class itself.
④ If you change the class attribute, all instances that are still inheriting that value (like r1 here) will be affected.
⑤ Instances that have overridden that attribute (like r2 here) will not be affected.
And now ...