简体   繁体   English

仅使用静态方法将数学方法继承到类中

[英]Inheriting math methods into a class with only static methods

I need to define a class which extends python's standard math module, without instantiating it (no need for that, all methods in the class are static): 我需要定义一个扩展 python标准数学模块的类,而无需实例化它(不需要这样做,该类中的所有方法都是静态的):

import math

class more_math(math):

    @staticmethod
    def add_func(x):
        return math.sqrt(x)+1

The code above doesn't run properly (script exits), with the error: 上面的代码无法正常运行(脚本退出),并显示以下错误:

TypeError: Error when calling the metaclass bases
    module.__init__() takes at most 2 arguments (3 given)

When the class declaration above is set to class more_math: , more_math.add_func(x) is called without error. 当上面的类声明设置为class more_math:more_math.add_func(x)被正确调用。 However, more_math.sqrt(x) [ sqrt is a method of math ] can't be called, as more_math doesn't have math as its base class. 但是, more_math.sqrt(x) [ sqrt是一种math方法]无法调用,因为more_math没有以math为基类。

Ideas on how could this be setup properly? 关于如何正确设置的想法?

Think long and hard about whether you actually need to provide the functions math implements. 想一想,是否真的需要提供数学实现的功能。 You almost certainly don't; 您几乎可以肯定不会; you probably just need to provide your extras. 您可能只需要提供您的额外费用。 That said, if you do need to provide a more_math module that implements all the standard math functions too, the easiest way to do this is to do a from math import * . 就是说,如果您确实需要提供同时实现所有标准数学函数的more_math模块,则最简单的方法是执行from math import * This will bring every function the math module defines into your module. 这会将math模块定义的每个函数带入您的模块。 This is considered very bad practice, because it pollutes the namespace of your module and can make it difficult to tell what is actually being used. 这被认为是非常不好的做法,因为它会污染模块的名称空间,并且可能使您很难分辨出实际使用了什么。 However, in this case, pollution of your module's namespace is exactly what you want . 但是,在这种情况下,污染正是您想要的

As @user2357112 commented math is a module and not a class. 正如@ user2357112所说,数学是一个模块,而不是一个类。 You can create a more_math module simply by creating a more_math.py file with: 您可以通过以下方式创建more_math.py文件来简单地创建more_math模块:

from math import *

def add_func(x):
    return sqrt(x)+1

this module can be imported with import more_math or from more_math import add_func . 该模块可以通过import more_math导入,也可以通过from more_math import add_func

math isn't a class, it's an instance of class types.ModuleType . math不是一个类,它是类types.ModuleType实例 You can verify this with isinstance(math, types.ModuleType) which will return True . 您可以使用isinstance(math, types.ModuleType)进行验证,该isinstance(math, types.ModuleType)将返回True Normally you can't define a subclass that inherits from an instance of another class. 通常,您不能定义从另一个类的实例继承的子类。 However, it is possible with a bit of hackery. 然而,这可能的一点两轮牛车的。
(I got the idea from a recipe for inheriting from an instances on the ActiveState website.) (我从 ActiveState网站上的实例继承的食谱中获得了灵感。)

Since it is a hack, one might not want to use it in production code. 由于它是一种hack,因此可能不想在生产代码中使用它。 However I thought you (and other readers) might find it a least interesting, if not useful. 但是,我认为您(和其他读者)可能会觉得它最没意思,即使没有用。

Script more_math.py : 脚本more_math.py

from copy import deepcopy
import math
import sys

def class_from_instance(instance):
    copy = deepcopy(instance.__dict__)

    def __init__(self, *args, **kwargs):
        super(InstanceFactory, self).__init__(*args, **kwargs)
        self.__dict__.update(copy)

    InstanceFactory = type('InstanceFactory',
                           (instance.__class__,),
                           {'__init__': __init__})
    return InstanceFactory

class MoreMathModule(class_from_instance(math)):
    @staticmethod
    def added_func(x):
        return math.sqrt(x)+1

# Replace this module with an instance of the class above.
ref, sys.modules[__name__] = sys.modules[__name__], MoreMathModule('more_math')

if __name__ == '__main__':
    import more_math
    x = 42
    print('more_math.sqrt({}) -> {:.6f}'.format(x, more_math.sqrt(x)))
    print('more_math.added_func({}) -> {:.6f}'.format(x, more_math.added_func(x)))

Output: 输出:

more_math.sqrt(42) -> 6.480741
more_math.added_func(42) -> 7.480741

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM