Fall 2026
  • Discord
  • Gradescope
  • Syllabus

On this page

  • A first class
  • The constructor
  • Methods
  • Dunder methods
  • Duck typing
  • Private attributes
  • When to use a class
  • Naming conventions
  • Classes in the final project

Objects & Classes

So far, every value we have written used a built-in type: int, float, str, bool, list, or dict. The class keyword defines a new type for the data we are modeling. Programming organized around classes is called object-oriented programming, or OOP (pronounced “oh oh pee”).

The final Twitter clone needs to store each tweet’s username, text, and like count, along with operations such as liking it.

A dictionary can bundle the data:

tweet = {'username': 'rtealwitter', 'text': 'my first tweet', 'likes': 0}

The dictionary holds the three values, but Python sees only a dict, and a separate like(tweet) function has no defined relationship to it:

>>> type(tweet)
<class 'dict'>

A class groups the data and operations under one name and defines a distinct type.

A first class

The simplest possible one is empty:

class Tweet:
    pass

class introduces a new type named Tweet, and pass is a do-nothing placeholder for the body. By convention a class name is capitalized, which is why it is Tweet and not tweet. This definition is enough to create objects of the new type:

>>> tweet = Tweet()
>>> type(tweet)
<class '__main__.Tweet'>

Tweet() builds a new object, and type confirms its type. An object is what a variable refers to, so the variable tweet refers to one. An instance is an object whose type is a particular class, so tweet is an instance of Tweet. “Object” and “instance” refer to the same value, with “instance” naming its relationship to a class.

This first Tweet has no attributes yet.

The constructor

Every tweet should begin with a username, text, and zero likes. The constructor, a special method named __init__, sets those attributes when Python creates an instance:

class Tweet:
    def __init__(self, username, text):
        self.username = username
        self.text = text
        self.likes = 0

__init__ is defined like any function, with def, but the double underscores front and back mark it as special. Its first parameter, self, is the instance being built. Python supplies it automatically to every method. The body stores the supplied username and text on the instance and initializes its likes to zero.

The variables stored on the object, username, text, and likes, are called attributes (some languages call them properties). Create a tweet by calling Tweet with its data, then access each attribute with a dot:

>>> tweet = Tweet('rtealwitter', 'my first tweet')
>>> tweet.username
'rtealwitter'
>>> tweet.likes
0

The call passes two arguments, 'rtealwitter' and 'my first tweet', although __init__ lists three parameters. Python fills self with the new object automatically, and the explicit arguments correspond to the parameters after it.

Methods

Attributes store data; methods define related operations. A method is a function defined inside the class, and like __init__ its first parameter is self, the instance it acts on. Define a like method:

class Tweet:
    def __init__(self, username, text):
        self.username = username
        self.text = text
        self.likes = 0

    def like(self):
        self.likes = self.likes + 1

like takes only self and adds one to that instance’s like count. Calling it twice changes likes to 2:

>>> tweet = Tweet('rtealwitter', 'my first tweet')
>>> tweet.like()
>>> tweet.like()
>>> tweet.likes
2

When you write tweet.like(), Python passes tweet in as self, so self.likes refers to this tweet’s counter. tweet.like() returns None because it changes self.likes instead of returning a value, so the REPL prints nothing after each call.

Dunder methods

Methods with double underscores at the front and back are called dunder methods (short for “double underscore”) or magic methods. Python calls them for built-in operations rather than requiring you to call them by name. You never write tweet.__init__(...) yourself; Python calls __init__ when you write Tweet(...). Other dunder methods customize Python’s built-in behavior: __str__ controls what print shows, and __eq__ controls what == means.

A tweet reading: British Python devs be like 'that's a constructor, __init__?', a pun on the British 'innit?'

Duck typing

Python often uses an object’s available operations instead of checking its declared type. Consider a function that shows a post:

def show(post):
    print(post.text)

show does not require a Tweet; it runs on any object with a .text attribute and fails on an object without one. This is called duck typing: if an object walks like a duck and quacks like a duck, Python treats it as a duck.

Duck typing meme: a photo of a duck captioned 'if it walks like a duck, and talks like a duck, then it's a duck.'

Private attributes

Many languages make some attributes private, allowing only the class’s methods to access them. Python instead uses a naming convention. Prefix an internal attribute with one underscore, as in self._likes, to tell other programmers not to access it directly. The underscore does not enforce this restriction.

The meme turns disagreements about private attributes into a class-structure joke:

Arm-wrestle meme: 'object-oriented programmers' and 'Marxists' as equally strong arms, both 'thinking about class structure,' with a caption about strong opinions on whether properties should be private.

When to use a class

Use a class when data and behavior belong together, as they do for Tweet, and use a plain function otherwise.

Photo of Edsger Dijkstra with the quote 'Object-oriented programming is an exceptionally bad idea which could only have originated in California,' captioned 'the more I look into the topic the more I agree with this statement.'

Edsger Dijkstra wrote the quote shown above. Automate the Boring Stuff, the book this course uses, does not need a chapter on classes. You can automate many tasks without defining a class yourself. You mainly need to recognize classes in libraries and other people’s code. Real Python’s object-oriented programming guide provides a more detailed introduction.

Naming conventions

Python’s official style guide, PEP 8 (a “Python Enhancement Proposal”), defines naming conventions. Class names use CamelCase: capitalize each word and run them together, like Tweet or HttpResponse. Everything else, meaning variables, functions, methods, and attributes, uses snake_case: lowercase words joined by underscores, like username, like, and input_name. Python code does not conventionally use lowerCamelCase (capitalized words but a lowercase first letter, like inputName), although other languages do.

Classes in the final project

The final Twitter clone uses User and Tweet classes similar to the example above. Each class defines its instances’ data in __init__ and provides methods that operate on that data.

The Pull Request tutorial covers git collaboration through branches, merges, and pull requests.