首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >玩对象创建游戏

玩对象创建游戏
EN

Stack Overflow用户
提问于 2011-11-01 05:18:27
回答 3查看 100关注 0票数 1

我有两个带有foo方法的类

代码语言:javascript
复制
Foo = type('Foo', (object,), {'foo': lambda s: 'Foo method'})
Bar = type('Bar', (object,), {'foo': lambda s: 'Bar method'})

我还有一些其他的类,我需要根据参数从上面的一个类中继承出来。

我的解决方案是:

代码语言:javascript
复制
class Subject(object):
    def __new__(cls, key):
        base = (Foo if key else Bar)

        name = cls.__name__ + base.__name__
        dict_ = dict(cls.__dict__.items() + base.__dict__.items())
        bases = (base, cls)

        t = type(name, bases, dict_)
        return base.__new__(t)

    def bar(self):
        return 'Subject method'

测试:

代码语言:javascript
复制
print(Subject(True).foo(), Subject(True).bar())
print(Subject(False).foo(), Subject(False).bar())

输出:

代码语言:javascript
复制
('Foo method', 'Subject method')
('Bar method', 'Subject method')

这个解决方案足够安全吗?或者我需要更多的信息?有没有更多的蟒蛇方式来做这种非常规的事情?

EN

回答 3

Stack Overflow用户

发布于 2011-11-01 05:24:57

我想大多数人都会看到上面的代码,并建议使用组合而不是继承。Subject将定义一个foo方法,该方法根据布尔值分派给正确的类。

或者,您可以根据需要使用工厂函数来创建Foo或Bar。

代码语言:javascript
复制
def subject(selector):
     'Factory function that chooses between Foo and Bar'
     return Foo() if selector else Bar()

如果需要,使Foo和Bar都继承自一个公共类,以便工厂函数始终返回该公共类的子类的实例。

票数 2
EN

Stack Overflow用户

发布于 2011-11-01 05:58:52

如果避免使用元类(魔术),代码将更具可读性(因此更具pythonic风格)。遵循Chris和Raymond提出的方法,即

使用合成:

代码语言:javascript
复制
class Subject(object):
    def __init__(self, key):
        self.foo = (Foo if key else Bar)().foo
    def bar(self):
        return 'Subject method'

或者使用工厂函数:

代码语言:javascript
复制
def Subject(key):
    class Subject(Foo if key else Bar):
        def bar(self):
            return 'Subject method'
    return Subject()
票数 1
EN

Stack Overflow用户

发布于 2011-11-01 05:41:25

下面是当前方法可能导致的一些意外行为的示例,即使Subject覆盖了FooBar中的某些内容,也会调用该方法的FooBar版本:

代码语言:javascript
复制
class Subject(object):
    # all of your current methods as they were above
    def foo(self):
        return 'Subject foo'

>>> Subject(False).foo()
'Bar method'

即使您可以通过在创建dict_的行将base.__dict__.items()放在cls.__dict__.items()之前来修复此问题,但我建议完全远离此方法,可能使用Chris Lutz的注释或Raymond's answer

如果你感兴趣的只是一个动态的方法,我建议你做以下事情。在Subject类中创建方法的私有版本,然后分配要在Subject.__init__()中使用的任何方法

代码语言:javascript
复制
class Subject(object):
    def __init__(self, key):
        self.foo = self._Foo_foo if key else self._Bar_foo
    def _Foo_foo(self):
        return 'Foo method'
    def _Bar_foo(self):
        return 'Bar method'

>>> Subject(True).foo()
'Foo method'
>>> Subject(False).foo()
'Bar method'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7959883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档