Classes
A class defines a type: the data an object of that type holds, and the operations available on it. Instantiating a class creates an object with its own attributes. Classes are worth writing when several values are always handled together and a set of operations applies specifically to that combination.
Reading classes matters more than writing them in this course. Biopython's
Seq, SeqRecord and SeqFeature, and the hgvs variant model, are all
classes, and using them requires understanding attributes, methods and the role
of self.
chr17 7676154 True
__init__ runs immediately after the object is created and assigns its initial
attributes. It is not a constructor in the sense used by some other languages;
the object already exists when it is called.
self is the object the method was called on, and is the first parameter of
every instance method. Python supplies it automatically: variant.is_snv()
calls is_snv(variant). Omitting self from a method definition produces a
TypeError on the first call.
String representation
Printing an object without a defined representation produces the class name and
a memory address, which is of no diagnostic value. __repr__ should return a
precise, unambiguous description, ideally one that resembles the expression
which would recreate the object.
Variant('chr17', 7676154)
[Variant('chr1', 100)]
!r in an f-string applies repr to the value, which is why the chromosome
appears quoted above. __repr__ is also what is shown for objects inside a
list, since containers display their elements using repr.
Class attributes and instance attributes
An attribute assigned in the class body is shared by every instance. An
attribute assigned in __init__ through self belongs to one instance. Use a
class attribute for a constant that is a property of the type itself.
GRCh38 GRCh38
A mutable class attribute is shared across all instances and modifying it through one instance affects every other, which is rarely intended.
Dataclasses
The dataclass decorator generates __init__, __repr__ and __eq__ from the
annotated attributes. For a class that principally holds data, this removes a
substantial amount of code that would otherwise be written by hand.
Variant(chrom='chr17', pos=7676154, ref='G', alt='A') True
Task
Write a Sequence class with:
__init__(self, name, bases)storing both, withbasesconverted to uppercase.length()returning the number of bases.gc_content()returning the GC fraction rounded to four decimal places, or0.0for an empty sequence.__repr__returning"Sequence(<name>, <length>bp)".
Converting to uppercase in __init__ allows every other method to assume a
single case, rather than repeating the conversion.
Test cases · 3
| # | via | input | expected stdout |
|---|---|---|---|
| 1 | stdin | TP53 atggcc | Sequence(TP53, 6bp) 6 0.6667 |
| 2 | stdin | chr17 GGGGCCCC | Sequence(chr17, 8bp) 8 1.0 |
| 3 | stdin | test ATAT | Sequence(test, 4bp) 4 0.0 |
Hints · 2
01Hint
Uppercase in __init__ so every method can assume uppercase bases.
02Hint
length() can be called from gc_content() as self.length().