python:函数指针中断多态性

2024-04-20 05:12:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在基类中存储函数签名的dict,并让子类覆盖其中一些函数签名。然而,我的实现似乎打破了多态性。我想要一些关于优雅的替代品的建议。谢谢!在

class Base:
    def __init__(self, key):
        self.FXN[key](self)

    def f(self):
        pass

    def g(self):
        pass

    a = 1
    FXN = {
        1 : f,
        2 : g
    }

class Child1(Base):
    def __init__(self, key):
        self.FXN[key](self)

    def f(self):
        print 'hi'

class Child2(Base):
    def __init__(self, key):
        self.FXN[key](self)

    def f(self):
        print 'hey'

    def g(self):
        print 'hello'

if __name__ == '__main__':
    Child1(1) # Nothing happens
    Child2(1) # Nothing happens
    Child2(2) # Nothing happens

澄清:编辑问题

编辑二:再次澄清问题

注释:在更复杂的情况下,每个构造函数都可以接受某种类型的对象。键是一个枚举,它标识对象类型并指定实例启动的路径。在

布鲁诺的解决方案:下面的布鲁诺先生给了我一个相对优雅的解决方案。在

^{pr2}$

Tags: key函数self编辑baseinitdefpass
3条回答

这将使您的示例实现您似乎想要的:

class Base:
    def __init__(self):
        self.FXN = {
            1 : self.f,
            2 : self.g
        }
    def f(self):
        pass

    def g(self):
        pass


def receive_some_bases():
    return [Child1(), Child2(), Child1(), Child2(), Child1()]

if __name__ == '__main__':
    for base in receive_some_bases():
        base.FXN[1]()
        base.FXN[2]()

更新: 根据你问题的最新更新,听起来你想要一个工厂。一本字典到一个类可能很合适:

^{pr2}$

FXN是一个类变量,不绑定到子类。它还引用dict中的原始f,g函数对象,而不是在子类中定义的名称。当执行bas类的body时,它们甚至不存在,应该如何处理呢?在

为什么不使用常规方法?这些将绑定到每个类。另外,您可以使用__init__()中的types.MethodType将函数绑定到每个实例。在

而且,请记住:一个实例/类的所有属性都已经存储在对象的dict(__dict__)中,因此实际上不需要创建自己的属性。在

这些不是“函数指针”,只是“函数”—Python的函数是第一类对象。而且它确实不能像您所期望的那样工作,因为您存储在Base.FXN中的是本地函数f和{}。在

有几种可能的解决方案,取决于您的实际用例(您什么也没说,我怀疑是XY problem),其中最简单的一种是将这些函数定义为简单的包装器,并将实现委托给另一个函数(然后根据需要在子类中重写该函数),即:

class Base(object):
    def f(self):
        return self._f()

    def _f(self):
        pass

    def g(self):
        return self._g()

    def _g(self):
        pass

    FXN = {
        1 : f,
        2 : g
    }


class Child1(Base):
    def _f(self):
        print 'hi'

class Child2(Base):
    def _g(self):
        print 'hello'

if __name__ == '__main__':
    c1 = Child1()
    c2 = Child2()
    c1 = Child1.FXN[1](c1) 
    c2 = Child1.FXN[2](c2) 

一个更复杂(但可能更有效,再次取决于您试图解决的real问题)的解决方案可以基于decorator(类decorators或function decorators)、自定义描述符或(和/或…)自定义元类。在

编辑:给出编辑后的示例,有两个简单的解决方案:

使用lambdas:

^{pr2}$

使用getattr()

class Base(object):
    def f(self):
        pass

    def g(self):
        pass

    FXN = {
        1 : "f",
        2 : "g",
    }

for base in receive_some_bases():
    getattr(base, base.FXN[1])() 
    getattr(base, base.FXN[2])() 

相关问题 更多 >