59

I want to create a kind of utility class which contains only static methods which are callable by the name class prefix. Looks like I'm doing something wrong :)

Here is my small class:

class FileUtility():

    @staticmethod
    def GetFileSize(self, fullName):
        fileSize = os.path.getsize(fullName)
        return fileSize

    @staticmethod
    def GetFilePath(self, fullName):
        filePath = os.path.abspath(fullName)
        return filePath

Now my "main" method:

from FileUtility import *
def main():
        path = 'C:\config_file_list.txt'
        dir = FileUtility.GetFilePath(path)
        print dir

and I got an error: unbound method GetFilePath() must be called with FileUtility instance as first argument (got str instance instead).

A have a few questions here:

  1. What am I doing wrong? Should not the static method be callable by classname?
  2. Do I really need a utility class, or are there other ways to achieve the same in Python?
  3. If I try to change the code in main I'm getting: TypeError: GetFilePath() takes exactly 1 argument (2 given)

The new main:

from FileUtility import *
def main():
    objFile = FileUtility()
    path = 'H:\config_file_list.txt'
    dir = objFile.GetFilePath(path)
    print dir
hichris123
  • 10,145
  • 15
  • 56
  • 70
ilyaw77
  • 937
  • 3
  • 10
  • 15

7 Answers7

92

You're getting the error because you're taking a self argument in each of those functions. They're static, you don't need it.

However, the 'pythonic' way of doing this is not to have a class full of static methods, but to just make them free functions in a module.

#fileutility.py:

def get_file_size(fullName):
    fileSize = os.path.getsize(fullName)
    return fileSize


def get_file_path(fullName):
    filePath = os.path.abspath(fullName)
    return filePath

Now, in your other python files (assuming fileutility.py is in the same directory or on the PYTHONPATH)

import fileutility

fileutility.get_file_size("myfile.txt")
fileutility.get_file_path("that.txt")

It doesn't mention static methods specifically, but if you're coming from a different language, PEP 8, the python style guide is a good read and introduction to how python programmers think.

Collin
  • 11,977
  • 2
  • 46
  • 60
  • Hi Collin, thank you for reply, I did as you suggested, plain python file with list of methods and in main: dir = FileUtility.GetFilePath(path) I got an error: unbound method GetFilePath() must be called with FileUtility instance as first argument (got str instance instead) – ilyaw77 Oct 04 '12 at 20:48
  • Sorry, left a stray self in there on the first run. Do you still have a FileUtility class somewhere? – Collin Oct 04 '12 at 20:50
  • 2
    The point is, you shouldn't have a class FileUtility. Just as you might write free functions in C++, you should do the same here. Module names (which map to files) should also be all lower case. – Collin Oct 04 '12 at 21:01
  • 1
    I've written in many languages for many, many years and strongly believe in OO as a methodology for complex systems. Many times, I want to share some type of constant for example. I understand "the Pythonic way" and everything, but where's the line between "Pythonic" and "good OO design" in an otherwise-OO system? – Will Jul 07 '13 at 23:10
  • 8
    Why is this not "good OO design"? If you add constants, they are in the namespace of the module. In C++ you would put the constants in a namespace, so the same applies here. In Python, a module is a name space. Putting variables in the top level of a module does not put them in the global namespace. – Vagrant Sep 01 '14 at 17:21
8

You really shouldn't be creating static methods in Python. What you should be doing is putting them at the global function level, and then accessing the module they're in when you call them.

foo.py:

def bar():
  return 42

baz.py:

import foo
print foo.bar()
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
7

Static methods don't get the object passed in as the first parameter (no object)

remove the self parameter and the calls should work. The import problem is relevant too. And the static comment relevant too.

SpKel
  • 542
  • 5
  • 15
Hedlok
  • 146
  • 3
4

In python, java-like (or whatever) static methods are not widely used as they don't really have a purpose.

Instead, you should simply define your "methods" as functions in a module:

#module1.py
def fun1():
    return do_stuff()
def fun2(arg):
    return do_stuff_with_arg(arg)

#main.py
import module1
if __name__ == '__main__':
    a = module1.fun()
    print module1.fun2(a)
Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • "they don't really have a purpose". I think they have a purpose, in that sometimes you want a method to both be inheritable (hence part of a class) and yet support static references. That and other use-cases exist in Python as outlined nicely in this answer: https://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python – ecoe Sep 09 '18 at 19:27
3

Just remove self in methods definition. Your intention is to use as static. Self is to work with instance of that class.

zozelfelfo
  • 3,776
  • 2
  • 21
  • 35
2

Just remove the self in the function definition. Since your using the static functions so you need not pass self as an argument for the functions. So your class and function should be like this:

class FileUtility():

    @staticmethod
    def GetFileSize(fullName):
        fileSize = os.path.getsize(fullName)
        return fileSize

    @staticmethod
    def GetFilePath(fullName):
        filePath = os.path.abspath(fullName)
        return filePath
Keerthana Prabhakaran
  • 3,766
  • 1
  • 13
  • 23
1

If you want to use your functions defined in the class, you have just to create an instance of your class and apply the function.

So the result is :

dir = FileUtility().GetFilePath(path)

Just add () after your class name.

@staticmethod is not needed as you are using standard function, not static. But in your case the result is the same.

Pollux31
  • 11
  • 1