<jupyter_start><jupyter_text>Classes====As you probably know, Python is an object-oriented language, and so it has very strong support for objects. In fact, everything in Python is an object. We will mostly use an imperative or functional rather than object-oriented programming style in this course. Here is the bare minimum about Python objects.  Defining a new class----We define a class A with two 'special' double underscore methods and one normal method. This class will have an attribute `x` that is specified at the time of creating new instances of the class.- The __init__ method initializes properties of any new instance of A- The __repr__ method provides an accurate string representation of A. For example, if we print an instance of A, the __repr__ method will be used. If you don't specify a __repr__ (or __str__) special method, the default name when printing only gives the address in memory.There are many more special methods, as described in the [official documentation](https://docs.python.org/3.5/reference/datamodel.html). We will not go there.<jupyter_code>class A:
    """Base class."""

    def __init__(self, x):
        self.x = x

    def __repr__(self):
        return '%s(%a)' % (self.__class__.__name__, self.x)

    def report(self):
        """Report type of contained value."""

        return 'My value is of type %s' % type(self.x)<jupyter_output><empty_output><jupyter_text>Docstrings----<jupyter_code>A.__doc__
help(A)
A.report.__doc__<jupyter_output><empty_output><jupyter_text>Creating an instance of a class----  Example of a class without __repr__.<jupyter_code>class X:
    """Empty class."""
x = X()
print(x)<jupyter_output><__main__.X object at 0x106e7fcc0><jupyter_text>Create new instances of the class A<jupyter_code>a0 = A('a')
print(a0)
a1 = A(x = 3.14)
print(a1)<jupyter_output>A(3.14)<jupyter_text>Attribute access<jupyter_code>a0.x, a1.x<jupyter_output><empty_output><jupyter_text>Method access<jupyter_code>a0.report(), a1.report()<jupyter_output><empty_output><jupyter_text>Class inheritance----<jupyter_code>class B(A):
    """Derived class inherits from A."""

    def report(self):
        """Overwrite report() method of A."""
        return self.x
B.__doc__<jupyter_output><empty_output><jupyter_text>Create new instances of class B<jupyter_code>b0 = B(3 + 4j)
b1 = B(x = a1)<jupyter_output><empty_output><jupyter_text>Attribute access<jupyter_code>b0.x
b1.x<jupyter_output><empty_output><jupyter_text>Method access<jupyter_code>b1.report()<jupyter_output><empty_output><jupyter_text>Nested attribute access<jupyter_code>b1.x.report()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10891089108910891, 'fraction_numerical': 0.011805026656511805, 'mean_word_length': 5.225118483412322, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 44, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '578667', 'license': 'MIT', 'n_tokens_mistral': 881, 'n_tokens_neox': 856, 'n_words': 260, 'path': 'notebook/03_Classes.ipynb', 'repo_name': 'cliburn/sta-663-2017', 'size': '2626'}