Skip to content

Class Attributes

Making things happen

To analyze a sample in the real world you would put the sample in a special device (like e.g. an Ion Proton Sequencer). While we should include something in our model to reflect this process, we will keep it a bit simpler.

Start by doing Task 5

One for all

We notice that the possible bases from which the analysis results are made up actually are the same, independent of which sequencer we use. This circumstance can be expressed with a class attribute. A class attribute is shared by all instances of a class. These class attributes are accessed via the class name and the .-operator

from random import choices

class DnaSequencer:

    BASES = ["A", "C", "G", "T"]
    # If it is written at the indentation level
    # directly below the class header, it is a class attribute
    # This time in upper case because we want this to be treated
    # as a constant, which are written this way by convention

    def __init__(self, ):
          # As before

    def clean():
        

    def analyze_sample(self, sample):
        if not self.is_clean:
            print("Sequencer", self.serial_number, "is still dirty - abort")
            return

        sequence_length = 2000
        dna_sequence = "".join(
            choices(
                DnaSequencer.BASES,  # Note how it is accessed
                k=sequence_length
            )
        )
        sample.take_analysis_result(dna_sequence)

        self.is_clean = False

Note that the analyze_sample-method triggers a modification of the object that was given for the sample parameter, even though it was not returned. This kind of “hidden” change of state is called a side-effect. Those can be convenient but are notoriously hard to debug! A side-effect-free variant would be to construct a copy of the sample-parameter, modify the copy and then return this modified copy.

Finish by doing Task 06

Note: Accessibility of Class Attributes

In Python you can access class attributes via ClassName.class_attribute_name. However, you can access class attributes also via self.class_attribute_name.

Python’s class attributes and object attributes are stored separately. When you reference the attribute of an object, Python first tries to look it up in the object. If it does not find it there, it checks the class. This is especially important when assigning values to class attributes:

Example:

class Car:
    color = "red"

my_car = Car()
print(my_car.color)        # "red"
my_car.color = "green"     # change this only for my_car -> becomes an instance attribute
print(my_car.color)        # "green"
print(Car.color)           # still "red"
Car.color = "blue"         # change this fo all cars
print(my_car.color)        # still "green", since instance attribute is present
print(type(my_car).color)  # "blue", since we first obtain the type/class and derive the color from that
del my_car.color           # remove the instance attribute
print(my_car.color)        # "blue" since it falls back to the class attribute again