Strange Coincidence
Great Stuff
Python not only offers generators with the yield
keyword; classes can also implement generators as iterators. For this the Pythonista defines two methods: __iter__()
and __next__()
. The quadruple underscores ("dunders") mark the official entry points for Python's standard library. If the Python interpreter sees a loop head like for n in Roulette()
, it instantiates an object of the Roulette
class, uses __iter__()
to access its iterator, and then retrieves new values from it with calls to __next__()
until the iterator throws an exception.
In the class defined in Listing 2, __iter__()
conveniently returns the Roulette
instance itself, because the class does not need a separate iterator, since it implements the iterator itself with __next__()
. The latter always returns a new random number in the range 0 to 36 and never throws an exception, so that the flow of the for
loop in the main program never stops.
Listing 2
roulette.py
01 #!/usr/bin/env python3 02 import random 03 04 class Roulette: 05 slots = 36 06 numbers = range(0,slots+1) 07 08 def __iter__(self): 09 return self 10 11 def __next__(self): 12 return self.__class__.numbers[random.randint(0, self.__class__.slots)]
The Roulette
class defines two class variables: slots
as the highest number on the roulette
wheel and numbers
as a sequence of numbers from 0 to 36 inclusive. It makes sense to define the variables once only for the class and not to rebuild them for each instance or even every time the iterator is called.
Class or Instance?
Python's class variables differ from instance variables in that they are not accessed with self.variable
, but with __class__.variable
or self.__class__.variable
. For read-only access, you could even reference the class variable using the self.variable
instance path.
But if you modify the latter, you may be in for a surprise, because Python creates a new instance variable behind your back. The instance variable will be decoupled from the class variable so that each object will modify its own, instead of propagating changes to the class level. Also, methods do not find the class variable simply by its name; if you simply reference slots
in __iter__()
, you can expect the syntax checker to blow up in your face.
As so often in the Python world, there is a small but subtle difference between versions 2 and 3: The iterator entry into the generator class goes by the name of next
in Python 2 and not __next__
as in Python 3; programmers who want to use both versions thus typically simply define another next()
method, which passes the parameters fed to it to __next__()
without modification. Python 3 does not use next()
, so the compatibility trick does no harm there.
The output of the statistical evaluation of the roulette generator is shown in Listing 3. After 27 rounds, a doublet appeared for the first time: the number 11 occurred twice in a row. After 6,249 rounds of Faites vos jeux, 15 occurred three times in a row; after 57,393 games, 34 occurred four times in a row, and so on.
Listing 3
roulette-run
1 $ ./roulette 2 max_run: 2 11 (27) 3 max_run: 3 15 (6249) 4 max_run: 4 34 (57393) 5 max_run: 5 1 (3363284) 6 max_run: 6 0 (95846456) 7 max_run: 7 26 (357289507)
Tumultuous Scenes
What would happen in Las Vegas at a roulette table if zero came up come six times in a row as in Listing 3 after 95 million rounds? Tumultuous scenes would probably take place in the casino before the pit boss appeared and sent the croupier home for the day, because every player at the table would immediately suspect that something fishy was going on. But, seen statistically, everything is above board; it's an inevitable fact that even random values will repeat at some time.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Direct Download
Read full article as PDF:
Price $2.95
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs
News
-
KDE Plasma 5.27 Beta is Ready for Testing
The latest beta iteration of the KDE Plasma desktop is now available and includes some important additions and fixes.
-
Netrunner OS 23 Is Now Available
The latest version of this Linux distribution is now based on Debian Bullseye and is ready for installation and finally hits the KDE 5.20 branch of the desktop.
-
New Linux Distribution Built for Gamers
With a Gnome desktop that offers different layouts and a custom kernel, PikaOS is a great option for gamers of all types.
-
System76 Beefs Up Popular Pangolin Laptop
The darling of open-source-powered laptops and desktops will soon drop a new AMD Ryzen 7-powered version of their popular Pangolin laptop.
-
Nobara Project Is a Modified Version of Fedora with User-Friendly Fixes
If you're looking for a version of Fedora that includes third-party and proprietary packages, look no further than the Nobara Project.
-
Gnome 44 Now Has a Release Date
Gnome 44 will be officially released on March 22, 2023.
-
Nitrux 2.6 Available with Kernel 6.1 and a Major Change
The developers of Nitrux have officially released version 2.6 of their Linux distribution with plenty of new features to excite users.
-
Vanilla OS Initial Release Is Now Available
A stock GNOME experience with on-demand immutability finally sees its first production release.
-
Critical Linux Vulnerability Found to Impact SMB Servers
A Linux vulnerability with a CVSS score of 10 has been found to affect SMB servers and can lead to remote code execution.
-
Linux Mint 21.1 Now Available with Plenty of Look and Feel Changes
Vera has arrived and although it is still using kernel 5.15, there are plenty of improvements sure to please everyone.