aberger
aberger

Reputation: 2397

Pass class attribute as parameter of a function of that class in Python

As the title indicates, I am trying to pass an attribute of my class as a parameter for a function of that same class. In the example below, the functionality of print_top_n() would be to print self.topn by default, but the function could also be called with a different value if need be. Is this a Python (or general programming) foul or is there a way to do this?

>>> class Example():
    def __init__(self, topn=5):
        self.topn = topn
    def print_top_n(self, n=self.topn):
        print n



Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    class Example():
  File "<pyshell#7>", line 4, in Example
    def print_top_n(self, n=self.topn):
NameError: name 'self' is not defined

Upvotes: 4

Views: 13593

Answers (3)

mgilson
mgilson

Reputation: 309841

The methods are created when the class is created, and the default values are set when the method is created (See this question/answer) -- They aren't re-evaluted when the function is called. In other words, this all happens long before self has been created (Hence the NameError).

The typical approach is to use a sentinel value that you can check inside of print_top_n (None is the most common).

def print_top_n(self, n=None):
    n = self.topn if n is None else n
    print n

Upvotes: 10

Michael Merickel
Michael Merickel

Reputation: 23331

One option is to use a marker object. This is a better pattern than n=None (depending on the actual intent of your api) because it will work even if someone passes n=None intentionally.

marker = object()

class Example:
    def __init__(self, topn=5):
        self.topn = topn

    def print_top_n(self, n=marker):
        if n is marker:
            n = self.topn
        print(n)

Upvotes: 4

chepner
chepner

Reputation: 530960

No; default values are evaluated when the function is defined, so there is no object yet to perform an attribute access on. You use a sentinel value instead:

def print_top_n(self, n=None):
    if n is None:
        n = self.topn
    print n

Upvotes: 0

Related Questions