Calling Class Staticmethod Within the Class Body

Calling class staticmethod within the class body?

staticmethod objects apparently have a __func__ attribute storing the original raw function (makes sense that they had to). So this will work:

class Klass(object):

@staticmethod # use as decorator
def stat_func():
return 42

_ANS = stat_func.__func__() # call the staticmethod

def method(self):
ret = Klass.stat_func()
return ret

As an aside, though I suspected that a staticmethod object had some sort of attribute storing the original function, I had no idea of the specifics. In the spirit of teaching someone to fish rather than giving them a fish, this is what I did to investigate and find that out (a C&P from my Python session):

>>> class Foo(object):
... @staticmethod
... def foo():
... return 3
... global z
... z = foo

>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>

Similar sorts of digging in an interactive session (dir is very helpful) can often solve these sorts of question very quickly.

How to call static methods inside the same class in python

In fact, the self is not available in static methods.
If the decoration @classmethod was used instead of @staticmethod the first parameter would be a reference to the class itself (usually named as cls).
But despite of all this, inside the static method methodB() you can access the static method methodA() directly through the class name:

@staticmethod
def methodB():
print 'methodB'
A.methodA()

How to call static method from inside of a class body?

The staticmethod is a descriptor. A descriptor exposes the __get__(instance, cls) method allowing it to be accessed either through an instance or at the class level.

Now in your case you wish to call it within a class stanza. Normally this would not be possible as neither an instance nor the class are yet available. However a staticmethod ignores both in any case so you can use the following rather nasty approach to call it.

class A:
@staticmethod
def foo():
return 12

baz = foo.__get__(None, object)()

Then

>>> A.baz
12

Note: The only reason to pass object as the second argument is that staticmethod insists on being passed a class of some kind as the second argument.

calling static method from inside the class

By using TestStatic.do_something() you'd bypass any override on a subclass:

class SubclassStatic(TestStatic):
@staticmethod
def do_something():
print 'I am the subclass'

s = SubclassStatic()
s.use_me()

will print

I am the subclass
I am static

This may be what you wanted, or maybe it wasn't. Pick the method that best fits your expectations.

Calling a static method with self vs. class name

You make a few statements that aren't entirely correct:

Calling Python static methods using the class name is more common

It's not more common, it's the only way to do so from outside the class. i.e.:

class MyClass:
@staticmethod
def a_method():
pass

MyClass.a_method()

In this example, self.a_method() would not work, as self would not refer to an instance of MyClass.

calling a static method with self is the same as ClassName.static_method(self), where self would be ignored by the static method

That's not actually the case, for example:

class MyClass:
@staticmethod
def a_method():
pass

def another_method(self):
# this is fine
self.a_method()
# this causes an error, as .a_method expects no arguments
MyClass.a_method(self)

self simply refers to the instance of the class that called an instance method (which has the self argument, which doesn't even have to be called self - it's just whatever the first parameter is called, self is the convention.

You can call static methods on self, because self is an instance of the class that has the static method, and thus has the method. You can also call static methods on classes directly, because a static method doesn't require an object instance as a first argument - which is the point of the static method.

You're fine using self.a_method() where you like, just keep in mind that self will refer to an object of the class the object was instanced as, not the specific class you mention.

For example:

class ClassA:
@staticmethod
def a_method():
print('a')

def another_method(self):
# prints whatever a_method for the class of self prints
self.a_method()
# always prints 'a', as a_method for ClassA prints 'a'
ClassA.a_method()

class ClassB(ClassA):
@staticmethod
def a_method():
print('b')

a = ClassA()
a.another_method()
b = ClassB()
b.another_method()

The output:

a
a
b
a

So, you see, there is a difference between calling from self. and from Class.

Why I got TypeError if calling staticmethod without class-body?

A static method is a method that is bound to a class but does not require the class instance to function.
For example, you may have a class built around a file type to retrieve raw data from a source file and pass it to a lexer, your constructor could have you pass in the raw file however you may want another function to open the file, validate it and retrieve the data. In this case, you could use a static function within the class as the function is related to the class but doesn't require the class to function (in this case it would return the actual class).

A code example:


class PythonFile:

def __init__(self, raw_data):

self._raw_data = raw_data
self._lexer = None

@staticmethod
def open(fp):
with open(fp, "r") as rFile:
data = rFile.read()
# validate, etc...
return PythonFile(data)

def lex(self):
self._lexer = PythonLex(self._raw_data)
return self._lexer.get_master_block_array()

# etc, etc...

python_file = PythonFile.open("some\\path.py")
print(python_file.lex())

ItzTheDodo.

How to call static method by reference?

In order to call a static method from inside your class you need to unwrap it. change m() to m.__func__('params') and you'll be good.

How to call static method from a static variable inside a class?

It looks like you'd like to initialize the value of a static class variable using a static function from that same class as it's being defined. You can do this using the following syntax taken from this answer but with an added parameter:

class X:
@staticmethod
def do_something(par):
return par

static_var = do_something.__func__(5)

print(X.static_var)

Output:

5

Try it!

Referencing a static method of the class X directly inside the X definition fails because X doesn't yet exist. However, since you have defined the @staticmethod do_something, you can call its __func__ attribute with the parameter and assign the result to static_var.

Having said that, more information about the underlying design goal you're trying to implement could reveal a better approach.

Can Python Staticmethod Call Another Local Method?

class Tester:
def local(self):
print "I'm a local!"

@staticmethod
def another_stat():
print "I'm a static!"

@staticmethod
def stat(inst):
inst.local()
Tester.another_stat()

t = Tester()
Tester.stat(t)

# Out:
# I'm a local!
# I'm a static!

Yes, you can! By definition, instance methods need an instance to associate themselves with, but as long as you have that instance, you can call local methods just as you normally would.

To go into this in a little more depth, there's nothing special about the word self. That's a variable just like any other. Any instance method of a class MUST take in an instance of that class as its first parameter, and it's convention to call that parameter self, but you could just as easily use any other name.

If it helps you understand the distinction, these two statements are semantically equivalent:

t.local()

Tester.local(t)

The first is just syntactic sugar for the second. The second is using the class name to reference a method of the Tester class, then passes in the instance as the first parameter. The first simply pretends that local is a field of t and calls it, but that call is transformed into Tester.local(t) by the Python interpreter.

Thus, calling a static method is the same syntax as Tester.local(t), except the first parameter does not have to be an instance of that class.

So classmethods and staticmethods are called in the same way, but the difference is that a class method "knows" what class it's coming from. The first parameter of a class method is always a variable that contains the class that it's being invoked from. That way if the method is inherited, it knows which method it's coming from, where a staticmethod would not know. In your comment, you said this:

@classmethod 
def stat(cls):
cls.another_stat()

In this example, cls is a variable that contains the class that the method is being called from, not an instance of the class that it is being called from. That is why you can call static methods with cls - because it is equivalent to Tester



Related Topics



Leave a reply



Submit