• 4
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

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)
  # ...
      • 2
    • 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...

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.

  • 21
Reply Report
    • 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.

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.

  • 8
Reply Report
      • 1
    • 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.

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()
  • 2
Reply Report
    • 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)
      • 2
    • 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.

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).

  • 1
Reply Report

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?

  • 1
Reply Report

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.

  • 1
Reply Report

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
  • 1
Reply Report

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
Reply Report

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)
  • 0
Reply Report

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. :-)

  • 0
Reply Report

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]

  • 0
Reply Report

Trending Tags