0

In this tutorial, an entire class is defined as class DontAppend: pass. According to this Q&A on Stack Overflow, pass defines the class.

The consensus from Google, however, is that pass is a statement. I've never seen statements define a class other than within definitions of class methods.

As a statement, pass also doesn't define a named class attribute/property.

Since pass doesn't serve to define a method or an attribute, how does it actually define the class? Is this just a special convention, solely for defining an empty class?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
user2153235
  • 388
  • 1
  • 11
  • 1
    @Zero: No it doesn't. `pass` has nothing to do with abstractness, and a class defined as `class ClassName: pass` will be concrete. – user2357112 Jun 28 '23 at 18:32
  • 1
    @Zero that's not correct. `pass` simply means that the body of the class/method is not available/required, and it's still a valid class or method. – Ankit Jaiswal Jun 28 '23 at 18:33
  • 1
    " I've never seen statements define a class other than within definitions of class methods." I'm not sure I understand you. A class body *contains statements*. `pass` is a valid statement. – juanpa.arrivillaga Jun 28 '23 at 18:48
  • I put this into the question, but it was deleted. If you're going to downvote, please suggest in the comments how it could have been avoided. I researched the concepts and terminology as much as possible before posting and nothing was shedding light on this. – user2153235 Jun 28 '23 at 18:49
  • 1
    *"solely for defining an empty class?"* -- You got it! – wjandrea Jun 28 '23 at 18:54
  • 1
    Related: [What's the usage of empty class in Python](/q/61243808/4518341), [How to use "pass" statement?](/q/13886168/4518341), [Empty class constructor (style)](/q/56374995/4518341). Also [The Sentinel Object Pattern - Python Design Patterns](https://python-patterns.guide/python/sentinel-object/) – wjandrea Jun 28 '23 at 19:08
  • Thanks! For some reason, my Googling wasn't turning up with those. I could guess *why* `class ClassName : pass` is used, but I couldn't square this off with my misunderstanding that the class "body" (a new subtle term for me) could contain arbitrary statements that execute when the Python interpreter encounters the class definition statement. – user2153235 Jun 28 '23 at 19:14

4 Answers4

2

The pass statement in python can be used as a placeholder for future code (or it may always remain as pass).

A pass statement helps in avoiding the error where empty code is not allowed. All the following are valid python statements -

class XYX:
    pass

class SomeException(Exception):
    pass

if somecondition:
    pass
else:
    x = y + z

Empty code is not allowed in loops, function definitions, class definitions, or in if statements. pass helps in such cases. It is pretty common to create custom exceptions by inheriting base exception classes and leaving the class body as pass

Ankit Jaiswal
  • 22,859
  • 5
  • 41
  • 64
  • As far as I know (and I'm a perpetual newby in Python), `pass` is essentially a no-op statement and a class definition consists of declarations of properties and methods. Is this a special exception to allow a statement in the class definition, allowable only for defining an empty class? That's the part that I don't get. – user2153235 Jun 28 '23 at 18:44
  • 4
    @user2153235: Arbitrary statements are allowed in class definitions. You could `print` things or write your whole program directly in a class body if for some reason you really wanted to. – user2357112 Jun 28 '23 at 18:46
  • 2
    @user2153235 "a class definitions consists of declarations of properties and methods". No, a class definition body contains *arbitrary statements*. Those *may* end up defining attributes, but you can put anything you like. If you don't want anything, then you can use `pass` – juanpa.arrivillaga Jun 28 '23 at 18:47
  • Hmm, this is a revelation to me. If executable statements appear in a class definition but outside of a declaration of methods and properties, what triggers their execution? In C++ (from my experience decades ago), we have explicitly defined constructors for code that runs during object instantiation. Is that when such arbitrary statements run? How would such code be organized among the declaration of properties and methods? – user2153235 Jun 28 '23 at 18:53
  • @user2153235 **there are no declarations in Python**. A class statement is executed *at runtime* just like any other statement. See my answer. Again, such code can be organized *however you want*. Anything you could put at the module level can be put in a class body. – juanpa.arrivillaga Jun 28 '23 at 18:56
  • Thanks. I'm still trying to get my head around modules and whether/how they are different from classes. The constituent "things" are accessed using "dot" notation for both. – user2153235 Jun 28 '23 at 19:05
2

You say that

According to this Q&A on Stack Overflow, pass defines the class.

but no, you've misread the linked page. pass doesn't define the class. class DontAppend: pass defines the class.

In this usage, pass is just the class body, not the entire class definition. The class body is a sequence of arbitrary statements that will be executed to populate the class's namespace. You don't want to do anything in the body of this class, so pass, a statement that doesn't do anything, is an appropriate body to use.

After the class body executes (and does nothing, because it's just pass), the class statement will take the namespace (mostly empty, except for a few default contents) and create a new type object based on that namespace.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Thanks for that clarification of terminology. The answer in the linked Q&A doesn't really use the term "body", but rather, "building element". So this answer is edifying. By the way, would I be right in saying that executing the class body *doesn't* create a new type object? Isn't it instantiation that creates the object? – user2153235 Jun 28 '23 at 19:10
  • 1
    @user2153235: No. The type object is the object that represents *the class itself*, not an instance of the class. Executing a class statement creates a type object. – user2357112 Jun 28 '23 at 19:24
  • OK, thanks for clarifying again. I was wrongly interpreting the wording as "a new object of the newly defined type)". – user2153235 Jun 28 '23 at 19:34
1

Here is the specification for the syntax of the python class definition statement:

classdef    ::=  [decorators] "class" classname [inheritance] ":" suite
inheritance ::=  "(" [argument_list] ")"
classname   ::=  identifier

So, as you can see, everything after the colon : is part of a "suite" (generally, this suite is called "the class body", or the "body of the class definition statement").

Here is the specification for a suite:

suite         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement     ::=  stmt_list NEWLINE | compound_stmt
stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]

So basically, a "suite" is any series of statements. Here is a valid class definition:

>>> class Foo:
...     print("inside the class body")
...
inside the class body
>>>

(Note, the body is executed, a class definition is executable code). So any valid Python statement can go in a class body. So what is pass then? Here is the spec:

pass_stmt ::= "pass"

pass is a null operation — when it is executed, nothing happens. It is useful as a placeholder when a statement is required syntactically, but no code needs to be executed, for example:

def f(arg): pass # a function that does nothing (yet)

class C: pass # a class with no methods (yet)

So some statement is required in the class body, you cannot just leave it blank if you want the class to be empty. So in that case, you can simply use pass.

Note, if you want more nitty-gritty details about how a class definition statement is executed and how that namespace becomes the namespace of the class object, this link to the data model will be useful

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • Thanks! In your comment under my question, you said that the statements are run at "runtime". Here, your example clarifies that "runtime" is when the class definition is encountered by the interpreter. Coming from using classes in C++, VBA, Matlab, and Java, I get confused by the very notion of "runtime" when referring to a specific piece of source code. – user2153235 Jun 28 '23 at 19:02
0

In Python, classes are objects, and they can be used to represent values or concepts. In this case, DontAppend is an empty class with no methods or attributes defined. It is simply used as a unique object to serve as a default value for the new_elem argument in good_function.

By defaulting new_elem to DontAppend, the function can check if a specific value has been passed for new_elem by comparing it to DontAppend. If a different value is provided, it means that the caller explicitly passed a value for new_elem, and that value will be appended to the starter_list. If new_elem is DontAppend, it indicates that no specific value was provided, and the function skips appending to the list.

Essentially, DontAppend acts as a special sentinel value to distinguish between the cases where a specific value is provided and where no specific value is provided for new_elem. It allows for more flexibility in how the function is called and provides a way to handle optional arguments.

  • This is true, but it doesn't really explain the `pass` thing. – user2357112 Jun 28 '23 at 18:36
  • @user235712 You right, my bad. In the case of class DontAppend: pass, the pass statement doesn't define any methods or attributes within the DontAppend class. Instead, it is used as a placeholder to create an empty class. In Python, a class definition is a block of code, and it requires at least one indented statement inside the class block. By using pass as the statement within the DontAppend class, the class block becomes valid syntax, even though it doesn't define any methods or attributes. – samsdatascience Jun 28 '23 at 18:54