为什么`_isurl`是实例方法而不是numpy`DataSource`的静态方法?

时间:2015-07-30 11:11:37

标签: python oop numpy

DataSource模块中的numpy.lib._datasource类有一个简短的实例方法_isurl(self,path),用于测试path是否为净位置。它不以任何方式使用实例及其成员 确实(在python 3.3中)它可以在没有实际创建实例的情况下使用:

DataSource._isurl(None,path)

然而,正如我所看到的,这是静态方法的典型情况(甚至是在任何类之外定义的常规函数​​)。将它作为实例方法编写是否有任何好处?

1 个答案:

答案 0 :(得分:1)

我非常有信心因性能原因而没有这样做:

import sys

if sys.version_info[0] >= 3:
    from urllib.parse import urlparse
else:
    from urlparse import urlparse

class DataSource(object):

    def _isurl(self, path):
        scheme, netloc, upath, uparams, uquery, ufrag = urlparse(path)
        return bool(scheme and netloc)

    @staticmethod
    def _isurl_staticmeth(path):
        scheme, netloc, upath, uparams, uquery, ufrag = urlparse(path)
        return bool(scheme and netloc)

时序:

In [1]: ds = DataSource()

In [2]: %timeit ds._isurl_staticmeth('http://www.google.com')
The slowest run took 14.76 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 2.25 µs per loop

In [3]: %timeit ds._isurl('http://www.google.com')
The slowest run took 12.99 times longer than the fastest. This could mean that an intermediate result is being cached 
100000 loops, best of 3: 2.31 µs per loop

实际上,两种方法都产生几乎相同的字节码:

In [4]: import dis

In [5]: dis.dis(ds._isurl)
  9           0 LOAD_GLOBAL              0 (urlparse)
              3 LOAD_FAST                1 (path)
              6 CALL_FUNCTION            1
              9 UNPACK_SEQUENCE          6
             12 STORE_FAST               2 (scheme)
             15 STORE_FAST               3 (netloc)
             18 STORE_FAST               4 (upath)
             21 STORE_FAST               5 (uparams)
             24 STORE_FAST               6 (uquery)
             27 STORE_FAST               7 (ufrag)

 10          30 LOAD_GLOBAL              1 (bool)
             33 LOAD_FAST                2 (scheme)
             36 JUMP_IF_FALSE_OR_POP    42
             39 LOAD_FAST                3 (netloc)
        >>   42 CALL_FUNCTION            1
             45 RETURN_VALUE        

In [6]: dis.dis(ds._isurl_staticmeth)
 14           0 LOAD_GLOBAL              0 (urlparse)
              3 LOAD_FAST                0 (path)
              6 CALL_FUNCTION            1
              9 UNPACK_SEQUENCE          6
             12 STORE_FAST               1 (scheme)
             15 STORE_FAST               2 (netloc)
             18 STORE_FAST               3 (upath)
             21 STORE_FAST               4 (uparams)
             24 STORE_FAST               5 (uquery)
             27 STORE_FAST               6 (ufrag)

 15          30 LOAD_GLOBAL              1 (bool)
             33 LOAD_FAST                1 (scheme)
             36 JUMP_IF_FALSE_OR_POP    42
             39 LOAD_FAST                2 (netloc)
        >>   42 CALL_FUNCTION            1
             45 RETURN_VALUE

无论哪种方式,_isurl似乎都不太可能在性能危急的情况下使用。

我不能代表那些笨拙的开发者,但我想不出任何特别的理由,为什么不让_isurl成为静态方法而不是实例方法。如果我从头开始设计一个类似的类,那么我可能会使它成为静态方法或只是一个普通的旧模块函数。