首页 > 解决方案 > 将模块函数作为静态方法导入类

问题描述

我有一个 python 模块 helpers.py


def str_to_num(s: str):
    '''Converts to int if possible else converts to float if possible
    Returns back the string if not possible to convert to a number.
    '''
    # NOTE: These are not really funcs, but classes.
    funcs = [int, float]

    for func in funcs:
        try:
            res = func(s)
            break
        except ValueError:
            continue
    else:
        res = s

    return(res)

我有另一个模块string_number.py

from helpers import str_to_num

class StringNumber:

    def __init__(self, s):
        self.s = s

    str_to_num = str_to_num

    @property
    def value(self):
        return(self.str_to_num(self.s))

    def __repr__(self):
        return(f'{self.__class__.__name__}({repr(self.s)})')
>>> from string_number import StringNumber
>>> sn = StringNumber(1)
>>> sn.value 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "string_number.py", line 19, in value
    return(self.str_to_num(self.s))
TypeError: str_to_num() takes 1 positional argument but 2 were given

但是,这在从类访问函数时有效:

>>> StringNumber.str_to_num(1)
1

Q.1:为什么str_to_num从实例访问属性时需要两个参数?是自我传递给它吗?如果是这样,为什么?

现在,我知道我可以添加修改__init__方法以使其成为实例的属性

def __init__(self, s):
    self.s = s
    self.str_to_num = str_to_num

此外,我可以通过创建一个 Helper 函数类然后从它继承来解决这个问题。

from helpers import str_to_num

class Helper:
    @staticmethod
    def str_to_num(s):
        return(str_to_num(s))


class StringNumber(Helper):

    def __init__(self, s):
        self.s = s

    @property
    def value(self):
        return(self.str_to_num(self.s))

    def __repr__(self):
        return(f'{self.__class__.__name__}({repr(self.s)})')

Q: 2有没有办法不使用继承来制作模块函数,类的静态方法?或者这是一个非常糟糕的做法?

问:3假设我有一个helpers.py模块,有大量的模块功能。要将它们作为静态方法合并到我的类中,最好的方法是什么,而不是单独的Helper类?

标签: pythonoop

解决方案


Q.1:为什么从实例访问 str_to_num 属性时需要两个参数?是自我传递给它吗?如果是这样,为什么?

你写了“但是从类访问函数时这有效:StringNumber.str_to_num(1)”。它之所以有效,是因为您通过在类定义下定义方法将其声明为静态方法。

与静态方法相反,实例方法在调用时确实将实例作为第一个参数传递。所以当你调用instance.str_to_num(1)你的str_to_num(s: str)- 无论你的类型暗示它是一个字符串 - 接收实例作为s参数并抱怨值1没有变量来保存它。


推荐阅读