我正在使用的库有一个返回A类对象的函数。
a = the_lib.lib_function() # returns an object of type A
我有一个继承自A.
的班级B.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"
有更好的方法吗?
答案 0 :(得分: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
实例。例如:
A
这将为您提供一个函数,您可以像类一样使用该函数返回the_lib.lib_function()
返回的my_method
实例,但这些实例还将包含{{1}}。
答案 1 :(得分:1)
只是将B
未提供给A
的所有属性访问转发到您的目的吗?即像这样:
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
继承,这将阻止检查实例。此外,大多数__magic__
方法也需要手动换行。
答案 2 :(得分: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的子类,即使它不是A,也可以使用ABCs来欺骗isinstance
等。
或者您甚至可以将B实例转换为A实例(例如,通过更改其__class__
) - 但请记住,这将使其使用A的大多数dunder方法的实现(包括{{1} })。
如果你真的希望B成为一个子类,你可以编写一个复制属性的__getattr__
构造函数(或类方法替代构造函数)。同样,您可以使用一组静态属性或动态执行此操作(只需记住__init__
不处理__dict__
,动态__slots__
属性,__getattr__
和类似假属性,从内置/扩展类继承的一些属性等。)。
那么,哪一个是对的?
如果不知道你实际想要完成什么,就不可能回答这个问题。在某些情况下,所有这些都是正确的,尽管其中一些比其他情况更少。