在 python 中定义要在多个类中使用的函数

Define a function to be used in multiple classes in python

提问人:Gowzahr 提问时间:8/29/2023 更新时间:8/30/2023 访问量:33

问:

是否可以定义一个可以用作多个类一部分的函数?

我首先尝试了这个:

class solvers:
   def Euler(self):
      self.N += self.dNdt(N) * self.dt

class blob:
   # contents of blob go here

methods = solvers()
blob1 = blob()
blob1.solver = methods.Euler

但这只会从方法内部调用 Euler 的别名,留下 blob1。N 不变。 我也试过了

from copy import deepcopy

blob1.solver = deepcopy(methods.Euler)

但这种方法似乎没有改变方法blob1 中的 N

python-3.x 函数 复制

评论

0赞 Barmar 8/29/2023
您正在分配绑定方法。分配未绑定的方法:blob1.solver = solvers.solver

答:

0赞 Reedinationer 8/29/2023 #1

为什么不直接将求解器作为参数传递给 blob 对象呢?我会将代码结构为一个类,其中包含要实现的所有求解器的通用方法,然后可以从该类继承。最后,可以创建所需求解器的实例,并将其传递给 blob 类,如下所示:SolverEuler

class Solver:
    def __init__(self):
        self.N = 0
    # Add other generic solver methods here

class Euler(Solver): # Note that we inherit from Solver
    def __init__():
        super().__init__()  # Tells python to add all generic solver methods to this

    def Euler(self):
        self.N += self.dNdt(N) * self.dt

class blob:
    def __init__(self, solver):
        self.solver = solver

    def blah():
        self.solver.N = 0 # We can access N like this

    # contents of blob go here

blob1 = blob(solver=Euler())
blob1.solver.N = 0  # We can access N like this

现在您可以从内部访问。self.solver.Nblob

除非你说你打算在实例之间共享?不过,像这样共享集成步骤变量似乎是不正确的。self.N

编辑

我们可以将 blob 实例的参数传递给求解器的 init 函数,以在它们之间共享信息,根据您的注释,这似乎是您的目标

import abc
from abc import ABC

class Solver(ABC):  # Inheriting from ABC means this is just a template class
    def __init__(self, some_n):
        self.N = some_n  # Every Solver instance will be provided with an N variable at initialization
        self.dt = .01  # Every Solver can use this as a time step

    @abc.abstractmethod
    def iteration_step(self):
        pass

class Euler(Solver): # Note that we inherit from Solver
    def __init__(self, some_n): # The Euler solver will take the N argument, solely to pass to the initialization on the next line
        super().__init__(some_n)  # Now the Euler has a self.N property, as well as all other Solver methods

    def iteration_step(self):
        self.N += self.dNdt() * self.dt  # I don't think N needs to be supplied to self.DnDt() because that method can use self.N
        print(self.N)

    def dNdt(self):
        return self.N * 0.05

class blob:
    def __init__(self, solver_class: Solver, n_of_blob):
        self.solver = solver_class(n_of_blob)  # initialize the solver class

    def run(self):
        for x in range(100):
            self.solver.iteration_step()

blob1 = blob(solver_class=Euler, n_of_blob=1.0)  # Note that we remove parenthesis from Euler() so that we can make the instance of solver in blob.__init__()
blob1.run()
print("-" * 80)
for x in range(100):
    blob1.solver.iteration_step()

请注意,如果运行此示例,则会在输出中看到类似

1.051257959948049
--------------------------------------------------------------------------------
1.051783588928023

这是从使用方法到使用方法的过渡,表明变量在两个作用域中都可以访问blob1.run()blob1.solver.iteration_step()

评论

0赞 Gowzahr 8/29/2023
问题是 N 是 blob 的一个属性,需要由属于 blob 的其他函数访问(我想使用与求解器相同的方法定义它)。现在我认识到我可以传递 blob。N 到需要它的功能,但这并不像我想要实现的那样干净。
0赞 Reedinationer 8/30/2023
@Gowzahr请看我的编辑
0赞 Gowzahr 8/29/2023 #2

我发现符合我尝试执行的操作的解决方案如下所示:

def Euler(self):
   self.N += self.dNdt(N) * self.dt

class blob:
   def euler(self):
      Euler(self)      

这允许诸如

blob.euler()

blob.solve = blob.euler

blob.solve()