python 中的条件 class 继承
conditional class inheritance in python
我正在尝试在 Python 中动态创建 classes,并且我对 classes 和 class 继承比较陌生。基本上我希望我的最终对象根据不同的需要具有不同类型的历史记录。我有一个解决方案,但我觉得必须有更好的方法。我梦到了这样的东西。
class A:
def __init__(self):
self.history={}
def do_something():
pass
class B:
def __init__(self):
self.history=[]
def do_something_else():
pass
class C(A,B):
def __init__(self, a=False, b=False):
if a:
A.__init__(self)
elif b:
B.__init__(self)
use1 = C(a=True)
use2 = C(b=True)
我假设出于某种原因您无法更改 A 和 B,而您需要两者的功能。
也许你需要的是两种不同的classes:
class CAB(A, B):
'''uses A's __init__'''
class CBA(B, A):
'''uses B's __init__'''
use1 = CAB()
use2 = CBA()
The goal is to dynamically create a class.
我真的不建议动态创建 class。您可以使用一个函数来执行此操作,并且您可以轻松地执行诸如 pickle 实例之类的操作,因为它们在模块的全局命名空间中可用:
def make_C(a=False, b=False):
if a:
return CAB()
elif b:
return CBA()
但如果你坚持"dynamically creating the class"
def make_C(a=False, b=False):
if a:
return type('C', (A, B), {})()
elif b:
return type('C', (B, A), {})()
两种方式的用法是:
use1 = make_C(a=True)
use2 = make_C(b=True)
您可能并不真正需要它,这可能是一个 XY 问题,但在您学习语言时这些问题经常发生。您应该知道,您通常不需要像使用某些其他语言那样使用 Python 构建庞大的 class 层次结构。 Python 使用 "duck typing" -- 如果 class 有你想使用的方法,就调用它!
此外,在调用 __init__
时,实例已经存在。你不能(轻易地)在那个时候为不同的实例改变它(尽管,真的,一切皆有可能)。
如果您真的希望能够实例化一个class并根据您传递给构造函数的内容接收本质上完全不同的对象的实例,简单、直接的做法是使用 returns 个不同 class 实例的函数。
但是,为了完整起见,您应该知道 classes 可以定义一个 __new__
方法,该方法在 __init__
之前被调用。此方法可以 return class 的实例,或完全不同的 class 的实例,或任何它想要的东西。因此,例如,您可以这样做:
class A(object):
def __init__(self):
self.history={}
def do_something(self):
print("Class A doing something", self.history)
class B(object):
def __init__(self):
self.history=[]
def do_something_else(self):
print("Class B doing something", self.history)
class C(object):
def __new__(cls, a=False, b=False):
if a:
return A()
elif b:
return B()
use1 = C(a=True)
use2 = C(b=True)
use3 = C()
use1.do_something()
use2.do_something_else()
print (use3 is None)
这适用于 Python 2 或 3。对于 3 它 returns:
Class A doing something {}
Class B doing something []
True
我正在尝试在 Python 中动态创建 classes,并且我对 classes 和 class 继承比较陌生。基本上我希望我的最终对象根据不同的需要具有不同类型的历史记录。我有一个解决方案,但我觉得必须有更好的方法。我梦到了这样的东西。
class A:
def __init__(self):
self.history={}
def do_something():
pass
class B:
def __init__(self):
self.history=[]
def do_something_else():
pass
class C(A,B):
def __init__(self, a=False, b=False):
if a:
A.__init__(self)
elif b:
B.__init__(self)
use1 = C(a=True)
use2 = C(b=True)
我假设出于某种原因您无法更改 A 和 B,而您需要两者的功能。
也许你需要的是两种不同的classes:
class CAB(A, B):
'''uses A's __init__'''
class CBA(B, A):
'''uses B's __init__'''
use1 = CAB()
use2 = CBA()
The goal is to dynamically create a class.
我真的不建议动态创建 class。您可以使用一个函数来执行此操作,并且您可以轻松地执行诸如 pickle 实例之类的操作,因为它们在模块的全局命名空间中可用:
def make_C(a=False, b=False):
if a:
return CAB()
elif b:
return CBA()
但如果你坚持"dynamically creating the class"
def make_C(a=False, b=False):
if a:
return type('C', (A, B), {})()
elif b:
return type('C', (B, A), {})()
两种方式的用法是:
use1 = make_C(a=True)
use2 = make_C(b=True)
您可能并不真正需要它,这可能是一个 XY 问题,但在您学习语言时这些问题经常发生。您应该知道,您通常不需要像使用某些其他语言那样使用 Python 构建庞大的 class 层次结构。 Python 使用 "duck typing" -- 如果 class 有你想使用的方法,就调用它!
此外,在调用 __init__
时,实例已经存在。你不能(轻易地)在那个时候为不同的实例改变它(尽管,真的,一切皆有可能)。
如果您真的希望能够实例化一个class并根据您传递给构造函数的内容接收本质上完全不同的对象的实例,简单、直接的做法是使用 returns 个不同 class 实例的函数。
但是,为了完整起见,您应该知道 classes 可以定义一个 __new__
方法,该方法在 __init__
之前被调用。此方法可以 return class 的实例,或完全不同的 class 的实例,或任何它想要的东西。因此,例如,您可以这样做:
class A(object):
def __init__(self):
self.history={}
def do_something(self):
print("Class A doing something", self.history)
class B(object):
def __init__(self):
self.history=[]
def do_something_else(self):
print("Class B doing something", self.history)
class C(object):
def __new__(cls, a=False, b=False):
if a:
return A()
elif b:
return B()
use1 = C(a=True)
use2 = C(b=True)
use3 = C()
use1.do_something()
use2.do_something_else()
print (use3 is None)
这适用于 Python 2 或 3。对于 3 它 returns:
Class A doing something {}
Class B doing something []
True