-1

我正在使用的库有一个返回 A 类型对象的函数。

a = the_lib.lib_function()  # returns an object of type A

我有一个类 B,它继承自 A。

class B(A):
    def my_method(self):
        print "This is Travis's class"

我希望 B 的构造函数调用库函数并包装返回的 A 对象。我看到了这样做的另一个问题的答案:

class B(A):
    def __init__(self):
        a = the_lib.lib_function()
        self.__dict__ = a.__dict__

    def my_method(self):
        print "This is Travis's class"

有一个更好的方法吗?

4

3 回答 3

2

而不是通过尝试继承来添加功能A,只需猴子补丁A返回的实例the_lib.lib_function()。例如:

import types

def my_method(self):
    print "This is Travis's class"

def B():
    a = the_lib.lib_function()
    a.my_method = types.MethodType(my_method, a)
    return a

这将为您提供一个函数,您可以像类一样使用它来返回 的实例Athe_lib.lib_function()但这些实例也将包括my_method.

于 2013-06-12T23:00:45.707 回答
1

是否只转发所有BA适合您的目的的属性访问?即像这样:

class B(object):

    def __init__(self):
        self.__a = the_lib.lib_function()

    def __getattr__(self, name):
        return getattr(self.__a, name)

    # maybe define __setattr__ too, and other __magic__ methods

    def my_method(self):
        # ...

也就是说,这有一些警告。一方面,B不能从 继承A,这会挫败 instanceof 检查。此外,大多数__magic__方法也需要手动包装。

于 2013-06-12T22:47:07.327 回答
1

以下是您尝试做的一些替代方案。


如果您只需要my_method访问A实例的属性,则无需执行任何操作。Python 没有“私有属性”;self通过参数访问属性与通过任何其他参数访问属性之间没有区别。所以:

def my_method(a):
    a.state.count += 1
    print "This is Travis's class"
a = the_lib.lib_function()
my_method(a)

如果您真的想将该方法a作为绑定方法附加到该方法,则可以这样做而无需对类进行胡思乱想:

a = the_lib.lib_function()
a.my_method = types.MethodType(my_method, a, type(a))

如果您确实需要包装 A 实例,通常通过委托比通过继承更好。无论您是通过静态委派您需要的方法、在类定义之后动态构建委派方法、在构建时动态构建它们,还是只是动态地使用这些方法__getattr__来做到这一点,都取决于您的实际需求。


如果您希望 B 充当 A 的子类,即使它不是一个,您可以使用ABC来愚弄isinstance等。


或者您甚至可以将 B 实例转换为 A 实例(例如,通过更改它的__class__)——但请记住,这将使它使用 A 的大多数 dunder 方法(包括__getattr__)的实现。


如果您真的希望 B 成为子类,您可以编写一个__init__复制属性的构造函数(或类方法替代构造函数)。同样,您可以使用一组静态属性或动态地执行此操作(请记住,__dict__不处理__slots__、动态__getattr__属性@property和类似的假属性,从内置/扩展类继承的某些属性等)。


那么,哪一个是对的?

如果不知道你实际上想要完成什么,就不可能回答这个问题。在某些情况下,所有这些都是正确的,尽管其中一些是正确的比其他的少得多。

于 2013-06-12T23:10:36.817 回答