You don't need to reference the class inside itself, using bar instead of Test.bar will work fine.

class Test:
    @staticmethod
    def bar():
        pass

    FOO_DICT = {1: bar}


# You can access this outside of the class by simply using Test.FOO_DICT
print(Test.FOO_DICT)

However, there are cases where you really need to use a class in itself. For example

class Test:
    @staticmethod
    def bar():
        pass

    def test_with_other_of_same_instance(self, other: Test):
        print(other.FOO_DICT)

    FOO_DICT = {1: bar}

In this case,

  • I want to define a method that accepts an object of the same Test class.
  • I want to use python's type hinting to indicate that the expected argument is an instance of Test. This allows me get editor support and also so tools like pylance and mypy can notify me of possible errors if I passed a argument of wrong data type.

As at the time of this writing, I'll get a NameError: name 'Test' is not defined.

This is because by default I can't use a class within itself (It is possible later versions of python will change its default behavior, hence we won't be needing the solution below by that time).

But if you use Python versions from 3.7+ and you can't reference a class within itself, the simple solution came with PEP 563 - Postponed evaluation of annotations. It is implemented by adding a little line of code at the first line of the file

from __future__ import annotations
# other imports or code come afterwards


class Test:
    @staticmethod
    def bar():
        pass

    def test_with_other_of_same_instance(self, other: Test):
        print(other.FOO_DICT)

    FOO_DICT = {1: bar}

So you can use a class within itself in python by simply including that line at the beginning of the file.

Normally, if you use pylance or any similar tool, you get a warning or error display to show you that you imported something and didn't use it. But not in the case of annotations. You don't have to worry about any warning from your editor.

Note that this must occur at the beginning of the file otherwise you get a SyntaxError and versions earlier than 3.7 won't support this.

Answer from Victory Ifebhor on Stack Overflow
Top answer
1 of 3
19

You don't need to reference the class inside itself, using bar instead of Test.bar will work fine.

class Test:
    @staticmethod
    def bar():
        pass

    FOO_DICT = {1: bar}


# You can access this outside of the class by simply using Test.FOO_DICT
print(Test.FOO_DICT)

However, there are cases where you really need to use a class in itself. For example

class Test:
    @staticmethod
    def bar():
        pass

    def test_with_other_of_same_instance(self, other: Test):
        print(other.FOO_DICT)

    FOO_DICT = {1: bar}

In this case,

  • I want to define a method that accepts an object of the same Test class.
  • I want to use python's type hinting to indicate that the expected argument is an instance of Test. This allows me get editor support and also so tools like pylance and mypy can notify me of possible errors if I passed a argument of wrong data type.

As at the time of this writing, I'll get a NameError: name 'Test' is not defined.

This is because by default I can't use a class within itself (It is possible later versions of python will change its default behavior, hence we won't be needing the solution below by that time).

But if you use Python versions from 3.7+ and you can't reference a class within itself, the simple solution came with PEP 563 - Postponed evaluation of annotations. It is implemented by adding a little line of code at the first line of the file

from __future__ import annotations
# other imports or code come afterwards


class Test:
    @staticmethod
    def bar():
        pass

    def test_with_other_of_same_instance(self, other: Test):
        print(other.FOO_DICT)

    FOO_DICT = {1: bar}

So you can use a class within itself in python by simply including that line at the beginning of the file.

Normally, if you use pylance or any similar tool, you get a warning or error display to show you that you imported something and didn't use it. But not in the case of annotations. You don't have to worry about any warning from your editor.

Note that this must occur at the beginning of the file otherwise you get a SyntaxError and versions earlier than 3.7 won't support this.

2 of 3
5

If you want the dictionary to be in the class: define the function first and remove Test:

class Test:
    @staticmethod
    def bar():
         pass

    FOO_DICT = {1: bar}
Top answer
1 of 7
23

Update

In Python 3.11 the module is named typing instead of typing_extensions

from typing import Self


class Node:
    """Binary tree node."""

    def __init__(self, left: Self, right: Self):
        self.left = left
        self.right = right

This might be helpful:

from typing_extensions import Self


class Node:
    """Binary tree node."""

    def __init__(self, left: Self, right: Self):
        self.left = left
        self.right = right

typing_extensions offers a Self class to reference class itself which I think is most elegent way to self-reference(PEP 673).


As others have mentioned, you can also use string literals. But it comes to problem when you have multiple type hints.

# python 3.10
var: str | int

And then you write something like

class Node:
    def __init__(self, var: 'Node' | SomeClass):
        self.var = var

It will raise a TypeError: unsupported operand type(s) for |: 'str' and 'type'.

2 of 7
18

While this, as other answers have pointed out, is not a problem due to the dynamic typing, in fact, for Python3, this is a very real issue when it comes to type annotations. And this will not work (note a type annotation of the method argument):

class A:
    def do_something_with_other_instance_of_a(self, other: A):
        print(type(other).__name__)

instance = A()
other_instance = A()

instance.do_something_with_other_instance_of_a(other_instance)

results in:

   def do_something_with_other_instance_of_a(self, other: A):
   NameError: name 'A' is not defined

more on the nature of a problem here: https://www.python.org/dev/peps/pep-0484/#the-problem-of-forward-declarations

You can use string literals to avoid forward references

Other way is NOT using python3-style type annotation in such cases,

and this is the only way if you have to keep your code compatible with earlier versions of Python.

Instead, for the sake of getting autocompletion in my IDE (PyCharm), you can docstrings like this:

Update: alternatively, instead of using docstrings, you can use "type: " annotations in a comment. This will also ensure that mypy static type checking will work (mypy doesn't seem to care about docstrings):

🌐
Stack Overflow
stackoverflow.com › questions › 58292893 › class-variable-reference-itself
python - Class variable reference itself? - Stack Overflow
@Joshuah: That particular item is something unique defined by the class so it can be referenced (and recognized as such) when doing the second part of the initialization in the derived class' __init__(). Since it's not used until after the class has been defined, it avoids the issue of trying to reference the instance before it has been created. Think of it as a "placeholder".. ... I think I understand what you are attempting to say, but I will have to run the code myself both with and without that particular line to grasp exactly what it is for. ... @Joshuah: Didn't know you were asking about a particular line. Because of how name look-ups work in Python inside a class, self.THIS is equivalent to WorldLocation.THIS in this usage case, so it's a reference to the class attribute.
Find elsewhere
Top answer
1 of 2
4

Karl's answer is entirely right about everything, but there is certainly a way to make resize act as you're expecting.

Three steps:

  1. Make a copy of the tree
  2. Re-initialize the tree so it's the next size larger
  3. Set the enlarged tree's left to the copy of the original tree

    def resize(self,n):
            while self.size < n:
                new = self.copy()
                self.__init__(int(round(self.size, 2)) * 2)
                self.left = new
    
            print("size in resize",self.size)
    
    def copy(self):
            new = tree(1)
            new.left = self.left
            new.right = self.right
            new.size = self.size
            new.free = self.free
            return new
    

Basically, you were trying to do it backwards -- replace self and reuse self for self.left, instead of replacing self.left and reusing self.

2 of 2
2

self = t

This does not, and cannot be rewritten to, do what you want. There is nothing "special" about the name self in Python; it's just like any other variable (the fact that you have to pass it explicitly to methods should have been your first hint, unlike in languages that treat this as a keyword, should have been your first hint ;) ), and like all other variables, it has reference semantics.

self = t means "from this point onward (until another re-definition or the end of scope), self no longer refers to what that self parameter referred to, but instead to the value that t refers to".

Also, you have a typo in one case of your __init__ method ('rigt'), and I assume that the number of free nodes is supposed to be an invariant something like size - occupied; in which case it would be cleaner to count the occupied nodes and use a method or property to calculate the free ones, instead of trying to update that count on every modification.

(Moreover, what you seem to be trying to do is all kinds of un-Pythonic. In particular, the idea of a container having a specific "allocated size" is strange; that sort of thing normally only matters on the C side of the fence. What do you need a binary tree for? Also, this method isn't going to balance the tree at all. And what use is a tree if none of the nodes store any data?)

Top answer
1 of 2
2

This is actually a case for defining a metaclass.

I've never actually found a source of information which gives a complete, clear and satisfactory explanation as to what metaclasses are or how they work. I will try to enhance this answer with such information if required but for the time being I am going to stick to a solution for your present problem. I am assuming python 3.

Define an additional class, thus:

class ModelSerializerMeta(serializers.SerializerMetaclass):

    def __init__(cls, class_name, base_classes, attributes):

        super(ModelSerialiserMeta, cls).__init__(class_name, base_classes, attributes)
        Serializer.types[cls.Meta.oid] = [cls.Meta.model, cls]

Then use this as the metaclass of your Serializers, e.g.

class ProfileSerializer(serializers.ModelSerializer, metaclass=ModelSerializerMeta):

    class Meta:
        oid = 'profile'
        model = Profile
        fields = ['login', 'status']

Better yet, create some superclass for all your model serializers, assign the metaclass there, make all of your serializers inherit from that superclass which will then use the metaclass throughout.

2 of 2
1

Metaclasses are definitely the right answer unless your code can require python >= 3.6. Starting with 3.6 there is a new feature called the __init_subclass__ hook.

So you can do something like

class foo:

    @classmethod
    def __init_subclass__(cls, *args, **kwargs):
        Serializers.register_class(cls)

Whenever a child of Foo is defined, the __init_subclass__ method on Foo will be called, passing in the child class reference as cls.

🌐
Stack Overflow
stackoverflow.com › questions › 66707934 › deciding-to-use-class-itself-or-class-method
python - Deciding to use class itself or class method - Stack Overflow
Explore Stack Internal ... Save this question. Show activity on this post. ... Closed 5 years ago. I just wondering which way is the most efficient (or pythonic) for accessing statically defined methods inside a method. Let me clear my question. class ExampleClass: @staticmethod def do_something(): pass @staticmethod def do_anohter_thing(): pass · I want to call do_something inside of the do_anohter_thing. Should I use @classmethod or the class itself(ExampleClass)?
Top answer
1 of 4
37

There is no generic way for a function to refer to itself. Consider using a decorator instead. If all you want as you indicated was to print information about the function that can be done easily with a decorator:

from functools import wraps
def showinfo(f):
    @wraps(f)
    def wrapper(*args, **kwds):
         print(f.__name__, f.__hash__)
         return f(*args, **kwds)
    return wrapper

@showinfo
def aa():
    pass

If you really do need to reference the function, then just add it to the function arguments:

def withself(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        return f(f, *args, **kwds)
    return wrapper

@withself
def aa(self):
      print(self.__name__)
      # etc.

Edit to add alternate decorator:

You can also write a simpler (and probably faster) decorator that will make the wrapped function work correctly with Python's introspection:

def bind(f):
    """Decorate function `f` to pass a reference to the function
    as the first argument"""
    return f.__get__(f, type(f))

@bind
def foo(self, x):
    "This is a bound function!"
    print(self, x)


>>> foo(42)
<function foo at 0x02A46030> 42
>>> help(foo)
Help on method foo in module __main__:

foo(self, x) method of builtins.function instance
    This is a bound function!

This leverages Python's descriptor protocol: functions have a __get__ method that is used to create bound methods. The decorator simply uses the existing method to make the function a bound method of itself. It will only work for standalone functions, if you wanted a method to be able to reference itself you would have to do something more like the original solution.

2 of 4
20

http://docs.python.org/library/inspect.html looks promising:

import inspect
def foo():
     felf = globals()[inspect.getframeinfo(inspect.currentframe()).function]
     print felf.__name__, felf.__doc__

you can also use the sys module to get the name of the current function:

import sys
def bar():
     felf = globals()[sys._getframe().f_code.co_name]
     print felf.__name__, felf.__doc__
Top answer
1 of 2
2

If you want your method to access a class variable, you need to access it via the class name or via self. Either one should work:

class dli:
    switch = dlipower.PowerSwitch()
    # no need for an empty __init__ method
    def PowerOn(self, port):
        outlet = dlipower.Outlet(dli.switch)
        outlet.on(port)

Or:

class dli:
    switch = dlipower.PowerSwitch()
    def PowerOn(self, port):
        outlet = dlipower.Outlet(self.switch)
        outlet.on(port)

This still recreates the outlet every time you call PowerOn, but perhaps that's cheap...

You don't really need a class for this. The class variable switch is just a global variable tucked away in the class namespace. Since you don't have any other attributes (either class attributes or instance attributes), it might be simpler to just use an actual global instead:

# no dli class needed any more, just use top level variables and functions!

_switch = dlipower.PowerSwitch() # create a global PowerSwitch

def PowerOn(port):
    outlet = dlipower.Outlet(_switch)
    outlet.on(port)

I've used a name with an underscore for the global variable. That tells any other programmers looking at the code that it is an internal implementation detail, not part of your module's API. It's not "private" in the way some other programming languages mean (where the compiler prevents other code from accessing it), but it's Python's version of being private (where other code is discouraged, but not prevented from accessing internal stuff).

Speaking of naming conventions, you might want to change yours. The most common convention for Python code is to use CaptializedNames only for classes, and lower_case_names_with_underscores for most other things (functions, variables, etc.). Using a different convention isn't wrong per se, but it may make it more difficult for others to read your code.

2 of 2
0

If you're trying to pass a specific instance of a PowerSwitch object into the Outlet object you're instantiating within the PowerOn function, pass it into the function as an argument, as such:

def PowerOn(self, port, switch):
  outlet = dlipower.Outlet(switch)
  outlet.on(port)

Then, whenever you want to instantiate a new Outlet, just instantiate the PowerSwitch before the function call, and include it as an argument.

In order to reference a variable from outside a given function within a function, that variable must either be global (created outside any function or class), a class variable (created outside a function within a class), a variable created within the function, or an argument provided with the function.

🌐
GitHub
github.com › python › mypy › issues › 3661
Type of the same class inside the class · Issue #3661 · python/mypy
July 5, 2017 - I have a method that returns itself but it doesn't know the type of the class inside class TcpFlow(object): def __init__(self) -> None: self.matches = [] # type: List[str] def __enter__(self) -> TcpFlow: return self I got this error Trac...
Author: python