51

For a recursive function we can do:

def f(i):
  if i<0: return
  print i
  f(i-1)

f(10)

However is there a way to do the following thing?

class A:
  # do something
  some_func(A)
  # ...
martineau
  • 119,623
  • 25
  • 170
  • 301
KL.
  • 891
  • 2
  • 8
  • 6
  • 1
    Not clear what you want or mean. `class A:` doesn't create an object, so there's no `A` to refer to. See the solutions presented for possible things you could have meant... – Andrew Jaffe Jan 09 '10 at 23:50
  • 11
    @Andrew __class A:__ creates a _class object_ as classes in python are first class – Mark Roddy Jan 10 '10 at 02:00
  • [Forward references](https://www.python.org/dev/peps/pep-0484/#forward-references) – KaiserKatze Jun 03 '21 at 08:22

14 Answers14

43

If I understand your question correctly, you should be able to reference class A within class A by putting the type annotation in quotes. This is called forward reference.

class A:
  # do something
  def some_func(self, a: 'A')
  # ...

See ref below

  1. https://github.com/python/mypy/issues/3661
  2. https://www.youtube.com/watch?v=AJsrxBkV3kc
Chin Pang Yau
  • 555
  • 4
  • 3
  • 4
    What you describe is only useful for making type-annotations — very likely **not** what the OP is asking about… – martineau Jan 11 '21 at 00:45
  • This answer should instead go on a question that is actually about type hints, for example [How do I type hint a method with the type of the enclosing class?](https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class) – Karl Knechtel Sep 02 '22 at 06:16
  • Even though it's up voted, it's not a correct answer. See Mark Roddy's answer. – relent95 Oct 19 '22 at 05:25
20

In Python you cannot reference the class in the class body, although in languages like Ruby you can do it.

In Python instead you can use a class decorator but that will be called once the class has initialized. Another way could be to use metaclass but it depends on what you are trying to achieve.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
  • 1
    Why though? What makes a class definition-body different from a function-body in that respect? Given that functions and classes are both first class objects, the difference in their bodies is not immediately apparent to me. Edit: As another answer below points out, function bodies are *not* executed upon the definition itself being executed, whereas class bodies are executed as part of the class-definition execution. – Dubslow Oct 30 '17 at 08:33
  • 7
    How do you use class decorators and metaclasses to achieve this? An example would be great. – Pro Q Dec 17 '17 at 10:56
  • 1
    @ProQ: Well here's [one example](https://stackoverflow.com/a/65659983/355230). Here's [another](https://stackoverflow.com/a/13763534/355230). I'm sure there are many others if you search for them. – martineau Jan 11 '21 at 00:42
  • you can actually reference the class with the class named as the annotation but as a string instead of a normal reference – Brian Obot Jul 17 '23 at 19:03
14

You can't with the specific syntax you're describing due to the time at which they are evaluated. The reason the example function given works is that the call to f(i-1) within the function body is because the name resolution of f is not performed until the function is actually called. At this point f exists within the scope of execution since the function has already been evaluated. In the case of the class example, the reference to the class name is looked up during while the class definition is still being evaluated. As such, it does not yet exist in the local scope.

Alternatively, the desired behavior can be accomplished using a metaclass like such:

class MetaA(type):

    def __init__(cls):
        some_func(cls)

class A(object):
    __metaclass__=MetaA
  # do something
  # ...

Using this approach you can perform arbitrary operations on the class object at the time that the class is evaluated.

Mark Roddy
  • 27,122
  • 19
  • 67
  • 71
  • 2
    This is the only answer that explains *why* it cannot be done (function bodies are not executed merely upon definition, while class bodies are). Thanks for the clarification. – Dubslow Oct 30 '17 at 08:37
  • It's also one of relatively few answers that actually understands what OP wants to do. – Karl Knechtel Sep 02 '22 at 06:06
4

Maybe you could try calling __class__. Right now I'm writing a code that calls a class method from within the same class. It is working well so far.

I'm creating the class methods using something like:

@classmethod
    def my_class_method(cls):
       return None

And calling then by using:

x = __class__.my_class_method()
  • 1
    This only works if you have an instance of the class, and that also *isn't necessary to call classmethods anyway*. In OP's example, the goal is to *run code at the top level of the class body*. – Karl Knechtel Sep 02 '22 at 06:06
3

It seems most of the answers here are outdated. From python3.7:

from __future__ import annotations

Example:

$ cat rec.py
from __future__ import annotations
class MyList:
    def __init__(self,e):
        self.data = [e]
    def add(self, e):
        self.data.append(e)
        return self
    def score(self, other:MyList):
        return len([e
            for e in self.data
            if e in other.data])
print(MyList(8).add(3).add(4).score(MyList(4).add(9).add(3)))
$ python3.7 rec.py
2
OrenIshShalom
  • 5,974
  • 9
  • 37
  • 87
  • The question is absolutely not about type annotations - it was **asked in 2010**. It is definitely not possible to use `MyList` like this in a context like what OP is describing. Please see [How do I type hint a method with the type of the enclosing class?](https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class) for an appropriate question for this answer (although it is probably a duplicate there). – Karl Knechtel Sep 02 '22 at 06:17
2

There isn't a way to do that within the class scope, not unless A was defined to be something else first (and then some_func(A) will do something entirely different from what you expect)

Unless you're doing some sort of stack inspection to add bits to the class, it seems odd why you'd want to do that. Why not just:

class A:
    # do something
    pass

some_func(A)

That is, run some_func on A after it's been made. Alternately, you could use a class decorator (syntax for it was added in 2.6) or metaclass if you wanted to modify class A somehow. Could you clarify your use case?

Crast
  • 15,996
  • 5
  • 45
  • 53
2

Nope. It works in a function because the function contents are executed at call-time. But the class contents are executed at define-time, at which point the class doesn't exist yet.

It's not normally a problem because you can hack further members into the class after defining it, so you can split up a class definition into multiple parts:

class A(object):
    spam= 1

some_func(A)

A.eggs= 2

def _A_scramble(self):
    self.spam=self.eggs= 0
A.scramble= _A_scramble

It is, however, pretty unusual to want to call a function on the class in the middle of its own definition. It's not clear what you're trying to do, but chances are you'd be better off with decorators (or the relatively new class decorators).

bobince
  • 528,062
  • 107
  • 651
  • 834
2

If you want to do just a little hacky thing do

class A(object):
    ...
some_func(A)

If you want to do something more sophisticated you can use a metaclass. A metaclass is responsible for manipulating the class object before it gets fully created. A template would be:

class AType(type):
    def __new__(meta, name, bases, dct):
        cls = super(AType, meta).__new__(meta, name, bases, dct)
        some_func(cls)
        return cls

class A(object):
    __metaclass__ = AType
    ...

type is the default metaclass. Instances of metaclasses are classes so __new__ returns a modified instance of (in this case) A.

For more on metaclasses, see http://docs.python.org/reference/datamodel.html#customizing-class-creation.

Danny Roberts
  • 3,442
  • 23
  • 28
2

If the goal is to call a function some_func with the class as an argument, one answer is to declare some_func as a class decorator. Note that the class decorator is called after the class is initialized. It will be passed the class that is being decorated as an argument.

def some_func(cls):
    # Do something
    print(f"The answer is {cls.x}")
    return cls # Don't forget to return the class

@some_func
class A:
    x = 1

If you want to pass additional arguments to some_func you have to return a function from the decorator:

def some_other_func(prefix, suffix):
    def inner(cls):
        print(f"{prefix} {cls.__name__} {suffix}")
        return cls
    return inner

@some_other_func("Hello", " and goodbye!")
class B:
    x = 2

Class decorators can be composed, which results in them being called in the reverse order they are declared:

@some_func
@some_other_func("Hello", "and goodbye!")
class C:
    x = 42

The result of which is:

# Hello C and goodbye!
# The answer is 42
cdiggins
  • 17,602
  • 7
  • 105
  • 102
1

If you want to refer to the same object, just use 'self':

class A:
    def some_func(self):
        another_func(self)

If you want to create a new object of the same class, just do it:

class A:
    def some_func(self):
        foo = A()

If you want to have access to the metaclass class object (most likely not what you want), again, just do it:

class A:
    def some_func(self):
        another_func(A) # note that it reads A, not A()
carl
  • 49,756
  • 17
  • 74
  • 82
  • 2
    Just a clarification: in your last example, referring to "A" is known as the "class object", not a "metaclass", which is an entirely different concept. The metaclass of A in your example would be `types.ClassType` (or `type` if using new-style classes or python3) – Crast Jan 09 '10 at 23:55
  • While this is the solution to most practical problems, it is technically not the class body, but the method body, which matters at import time. –  Jul 19 '20 at 12:26
  • This question is not about instances. It is about **the class itself**. – Karl Knechtel Sep 02 '22 at 06:08
1

What do you want to achieve? It's possible to access a class to tweak its definition using a metaclass, but it's not recommended.

Your code sample can be written simply as:

class A(object):
    pass
some_func(A)
Tobu
  • 24,771
  • 4
  • 91
  • 98
1

Do remember that in Python, type hinting is just for auto-code completion therefore it helps IDE to infer types and warn user before runtime. In runtime, type hints almost never used(except in some cases) so you can do something like this:

from typing import Any, Optional, NewType

LinkListType = NewType("LinkList", object)


class LinkList:
    value: Any
    _next: LinkListType

    def set_next(self, ll: LinkListType):
        self._next = ll


if __name__ == '__main__':
    r = LinkList()
    r.value = 1
    r.set_next(ll=LinkList())
    print(r.value)

And as you can see IDE successfully infers it's type as LinkList:

PyCharm type inference in action

Note: Since the next can be None, hinting this in the type would be better, I just didn't want to confuse OP.

class LinkList:
    value: Any
    next: Optional[LinkListType]

ramazan polat
  • 7,111
  • 1
  • 48
  • 76
-1

It's ok to reference the name of the class inside its body (like inside method definitions) if it's actually in scope... Which it will be if it's defined at top level. (In other cases probably not, due to Python scoping quirks!).

For on illustration of the scoping gotcha, try to instantiate Foo:

class Foo(object):
    class Bar(object):
        def __init__(self):
            self.baz = Bar.baz
        baz = 15
    def __init__(self):
        self.bar = Foo.Bar()

(It's going to complain about the global name 'Bar' not being defined.)


Also, something tells me you may want to look into class methods: docs on the classmethod function (to be used as a decorator), a relevant SO question. Edit: Ok, so this suggestion may not be appropriate at all... It's just that the first thing I thought about when reading your question was stuff like alternative constructors etc. If something simpler suits your needs, steer clear of @classmethod weirdness. :-)

Community
  • 1
  • 1
Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212
-2

Most code in the class will be inside method definitions, in which case you can simply use the name A.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662