如何将一个类的本地函数存储在另一个类中?

How can I store a function, local to one class, in another class?

提问人:alexniem 提问时间:8/31/2023 更新时间:8/31/2023 访问量:52

问:

我有两个类,Window 和 Page。每个页面都有一个唯一的 ID。我在 Page 类中有一些函数叫做 和 ,我想将它们存储在字典的 Window 类中,如下所示: ,键是页面的 id。我希望能够从 Window 类中的字典中获取值,然后能够调用 Page 类中的函数。self.render_page1()self.render_page2()self.pages = {"1":render_page1, "2":render_page2}

我目前的代码是:

class Window:
   def __init__(self):
      self.pages = {"1":(Page("1", self), render_page1), "2":(Page("2", self), render_page2)}

class Page:
    def __init__(self, id, window):
        self.id = id 
        self.window = window
        self.display_page()

    def display_page(self):
        self.window.pages[id][1]()

    def render_page1(self):
        pass

    def render_page2(self):
        pass

我认为问题是子例程是 Page 类的本地,因此它们需要以不同的方式存储在 Window 中。render_page

Python 函数 字典

评论

1赞 S.B 8/31/2023
您可以为它们加上前缀Page.
0赞 matszwecja 8/31/2023
您是否尝试使每个对象都有自己的方法?Pagerender_page
2赞 S.B 8/31/2023
但是,我对你为什么要这样做有点困惑
0赞 JonSG 8/31/2023
当您使用您可能想要执行的两个页面初始化窗口时,您可以 .但是,既然已经是,还需要存储渲染方法吗?你不能通过吗?p1 = Page("1", self)self.pages = {"1":(p1, p1.render_page1)}self.pages[1]p1self.pages[1][0].render_page1
0赞 alexniem 8/31/2023
@matszwecja我当前的解决方案是每个对象都有每个方法,它只调用它需要的方法。但是,如果有一种方法可以让每个对象只拥有它需要的方法,那么这将是理想的。Pagerender_pagePagerender_page

答:

0赞 gog 8/31/2023 #1

在 Python 中,有多种方法可以间接调用方法。如果你有

class A:
    def some_func(self):
        ...

您可以存储一个元组并使用以下命令调用它:object, method_namegetattr

tup = A(), 'some_func'

# later on

obj, name = tup
getattr(obj, name)()

或者,您可以存储指向该方法的指针,并使用对象作为第一个参数(称为)调用它:self

tup = A(), A.some_func

# later on

obj, fn = tup
fn(obj)

或者,您可以简单地将其存储并作为普通函数调用,这要归功于 Python 自动绑定功能:object.method

stored_fn = A().some_func

# later on

stored_fn()
0赞 S.B 8/31/2023 #2

由于这些函数位于类的命名空间内,因此应使用前缀访问它们。PagePage.

但是,我想我不太明白你为什么需要这个。如果您的目标是按 id 获取页面并根据不同的对象调用方法,则可以存储“Method”对象而不是函数。作为对实例的引用的方法对象。因此,无需单独存储实例。PagePage

from __future__ import annotations
from typing import Any, Callable, TypeAlias

Method: TypeAlias = Callable[..., Any]

class Window:
    def __init__(self):
        self.pages: dict[str, Method] = {}

    def add_page(self, page: Page, method_name: str) -> None:
        bound_method = getattr(page, method_name)
        self.pages[page.id_] = bound_method

class Page:
    def __init__(self, id_: str, window: Window):
        self.id_ = id_

    def render_page1(self):
        pass

    def render_page2(self):
        pass

window = Window()
page = Page("1", window)
window.add_page(page, "render_page1")

另一种方法是将 id 和 method 对象直接传递给 method:add_page

from __future__ import annotations
from typing import Any, Callable, TypeAlias

Method: TypeAlias = Callable[..., Any]

class Window:
    def __init__(self):
        self.pages: dict[str, Method] = {}

    def add_page(self, page_id: str, method: Method) -> None:
        self.pages[page_id] = method

class Page:
    def __init__(self, id_: str, window: Window):
        self.id_ = id_

    def render_page1(self):
        pass

    def render_page2(self):
        pass

window = Window()
page = Page("1", window)
window.add_page(page.id_, page.render_page1)