Calling a function stored in a class attribute: different behavior with a built-in function versus a normal function

With the following script:

import time

class Foo(object):
    func = time.gmtime
    def go(self):
        return self.func(0.0)

print time.strftime('%Y', Foo().go())

I get the following output:

1970

However, if I make a small modification and complete time.gmtime:

import time

def tmp(stamp):
    return time.gmtime(stamp)

class Foo(object):
    func = tmp
    def go(self):
        return self.func(0.0)

print time.strftime('%Y', Foo().go())

then I get the following error:

Traceback (most recent call last):
  File "./test.py", line 13, in <module>
    print time.strftime('%Y', Foo().go())
  File "./test.py", line 11, in go
    return self.func(0.0)
TypeError: tmp() takes exactly 1 argument (2 given)

Obviously, it is trying to call Foo.funcas if it were an instance method and passed selfas the first argument.

Two questions:

  • Both time.gmtimeand tmpare functions that take one argument, so why do the two scripts behave differently?
  • How can I safely store a regular function in the class / instance attribute and call it later from the instance method?
+4
3
  • time.gmtime tmp - , , -?

, Python,

self.func

,

, , . , , ( ) , : . , , .

, func self, , , , .

,

print type(time.gmtime)

class Foo(object):
    func = time.gmtime
    def go(self):
        print type(self.func)
        return self.func(0.0)

go Foo().go(),

<type 'builtin_function_or_method'>
<type 'builtin_function_or_method'>

. time.gmtime ( ), . ,

def tmp(stamp):
    return time.gmtime(stamp)

print type(tmp), tmp

class Foo(object):
    func = tmp
    def go(self):
        print type(self.func), self.func
        return self.func(0.0)

<type 'function'> <function tmp at 0x7f34d9983578>
<type 'instancemethod'> <bound method Foo.tmp of <__main__.Foo object at ...>>

tmp , , , Object Foo . , tmp Foo instancemethod. go Foo().go(), tmp,

Foo.func(self, 0.0)

tmp(self, 0.0)

:

TypeError: tmp() takes exactly 1 argument (2 given)
  1. class/instance ?

1:

Python,

, , , ; , .

, , , . , , .

, ,

import time

def tmp(stamp):
    return time.gmtime(stamp)

class Foo(object):
    def __init__(self):
        self.func = tmp       # Instance variable, not a class variable

    def go(self):
        return self.func(0.0)

print time.strftime('%Y', Foo().go())

self.func tmp(0.0), .

2:

staticmethod ,

class Foo(object):
    func = staticmethod(tmp)

    def go(self):
        # `return Foo.func(0.0)` This will also work
        return self.func(0.0)

self.func tmp.

class Foo(object):

    @staticmethod
    def func(stamp):
        return time.gmtime(stamp)

    def go(self):
        # `return Foo.func(0.0)` This will also work
        return self.func(0.0)
+3

...:

>>> import time
>>> type(time.gmtime)
<type 'builtin_function_or_method'>
>>> def f(*a): return time.gmtime(*a)
... 
>>> type(f)
<type 'function'>

A <type 'function'> ( ) , <type 'builtin_function_or_method'> ( )...

: " class/instance ?".

" " <type 'function'>, staticmethod, self . , , staticmethod , . , !

+2

, :

class Foo(object):
    def __init__(self):
        self.func = tmp

    def go(self):
        return self.func(0.0)

, .

, .

0

All Articles