asherbret
asherbret

Reputation: 6038

Access static method from static variable

There are plenty answers for how to access static variables from static methods (like this one, and that one, and the great info on the subject here), however I'm having trouble with the other direction: How can you use static methods to initialize static variables. E.g.:

import os, platform
class A(object):
    @staticmethod
    def getRoot():
        return 'C:\\' if platform.system() == 'Windows' else '/'
    pth = os.path.join(A.getRoot(), 'some', 'path')

The last line gives an exception: NameError: name 'A' is not defined. The same error happens if I use @classmethod instead of @staticmethod.

Is it possible to access a static method from a class variable?

Upvotes: 6

Views: 1089

Answers (3)

Emile
Emile

Reputation: 2971

The problem is that the class "A" doesn't exist yet at the moment your variable path is declared, so the evaluation fails. How about declaring it right after?

import os, platform
class A(object):
    @staticmethod
    def getRoot():
        return 'C:\\' if platform.system() == 'Windows' else '/'
A.pth = os.path.join(A.getRoot(), 'some', 'path')

An uglier alternative would be:

import os, platform
class A(object):
    @staticmethod
    def getRoot():
        return 'C:\\' if platform.system() == 'Windows' else '/'
    pth = os.path.join(getRoot.__func__(), 'some', 'path')

... but it's pretty unreadable (and depends on implementation details of @staticmethod, which is bad).

For this specific case I'd do something like this (which doesn't really answer your question, instead it sidesteps the need for it):

import os, platform
class A(object):
    _root = 'C:\\' if platform.system() == 'Windows' else '/'
    @staticmethod
    def getRoot():
        return A._root
    pth = os.path.join(_root, 'some', 'path')

... because your platform is pretty unlikely to change while your program is still running, right? :) If you have a better reason to do something like that, maybe use one of the methods above.

Upvotes: 5

asherbret
asherbret

Reputation: 6038

What I did in the end was have A extend a different class B which has the staticmethod I wanted. I.e.:

import os
import platform

class B(object):
    @staticmethod
    def getRoot():
        return r'C:\\' if platform.system() == 'Windows' else '/'

class A(B):
    pth = os.path.join(B.getRoot(), 'some', 'path')

Although this is what worked best for me it is more a work around rather than an answer.

Upvotes: -1

shx2
shx2

Reputation: 64328

You can defer the evaluation of pth by using a classproperty:

class A(object):
    @staticmethod
    def getRoot():
        return 'C:\\' if platform.system() == 'Windows' else '/'
    @classproperty
    def pth(cls):
        return os.path.join(cls.getRoot(), 'some', 'path')

classproperty is not a builtin, but it is a widely used recipe.

As a side note, IMHO, you should always prefer using classmethod over staticmethod.

Upvotes: 1

Related Questions