python 中的继承 - 如何使一个方法既是类方法又是常规方法?
inheritance in python - how to make a method both a classmethod and a regular method?
假设我在class中有一个方法,其结构如下:
class TestClass(object):
...
def __init__(self, ...)
...
self.var1 = ...
self.var2 = ...
...
...
def xyz(self, other)
if isinstance(other, TestClass):
...
self.var1 = ...
...
else:
...
self.var2 = ...
...
现在假设我想写另一个 class NewTestClass
继承自 TestClass
(即 class NewTestClass(TestClass): ...
)。
方法 xyz
的一个问题是它明确检查 other
变量是否是 TestClass
的实例并且它还引用实例的属性(即 self.var1
, self.var2
).
(a) 如何重写方法 xyz
以便在继承时(在 NewTestClass
中),if
语句的行为类似于 if isinstance(other, NewTestClass): ...
(我不不必在 NewTestClass
) 中重写方法 xyz
?
(b) 同样,假设我在 TestClass
中有另一个 method
引用 TestClass
中的 staticmethod
,例如:
@staticmethod
def abc(x):
...
val = ...
...
return val
def mnp(self, ...):
...
x1 = ...
self.var1 = TestClass.abc(x1)
...
此处,方法 mnp
使用 staticmethod
of TestClass
(即本例中的 TestClass.abc
)。我如何重写 TestClass.abc
,以便当 NewTestClass
继承 TestClass
时,它得到一个方法 mnp
将 self.var =
行视为等同于 self.var1 = NewTestClass.abc(x1)
(而且我不必在 NewTestClass
中重写方法 mnp
)?
你可以做一些丑陋的反射来让它工作,但这不是正确的做法。如果 classes 想自然地相互延伸 - 做,如果不是 - 不要。
就是说,您可以做的一件事是更改当前的实现,而不是分配一个 var - 调用另一个这样做的函数,并在每个 class 中实现此函数以修改正确的变量。
例如,更改:
def xyz(self, other)
if isinstance(other, TestClass):
...
self.var1 = ...
...
else:
...
self.var2 = ...
...
至:
def xyz(self, other)
if isinstance(other, TestClass):
...
self.modifyVar(value)
...
else:
...
self.var2 = ...
...
然后 class 您将实现:
def modifyVar(self, value):
self.var1 = value
在另一个 class 中,您将拥有:
def modifyVar(self, value):
self.var2 = value
这个答案涵盖了两种情况(静态和非静态函数)。
一)
def xyz(self, other):
if isinstance(other, self.__class__):
...
b) 您可以使用 self
:
调用静态 class 方法
def mnp(self, ...):
....
self.var1 = self.abc(...)
对于(a)部分,您需要检查other
是否是与self
相同的class的实例:
class TestClass(object):
def xyz(self, other):
if isinstance(other, self.__class__):
...
self.var1 = ...
...
else:
...
self.var2 = ...
...
通常认为 'pythonic' 尽可能避免 isinstance
这种逻辑。考虑使用 Python 的鸭子类型。以下示例不会完全满足您的需要,因为这两个属性都存在于您的 class 中。但是,如果您为实际代码选择了适当的异常,则此技术将起作用。
class TestClass(object):
def xyz(self, other):
try:
self.var1 = ... # The minimum code required to raise the exception
except AttributeError:
self.var2 = ...
else:
pass # Any other code if the exception is not raised
Python 的异常处理是轻量级的,旨在以这种方式使用。如果传入意外(可能尚未考虑),它会使您的代码更具弹性。
对于(b)部分,调用静态方法时不需要指定class。它可以在实例 (self
) 上调用。
class TestClass(object):
@staticmethod
def abc(x):
return x # Do something useful
def mnp(self, x):
self.var1 = self.abc(x)
现在,当您在派生的 class 中声明一个新的静态方法时,它将被正确调用:
class NewTestClass(TestClass):
@staticmethod
def abc(x):
return x * 2 # Do something else useful
a = NewTestClass()
a.mnp(1)
assert a.var1 == 2 # because NewTestClass.abc was called by mnp
假设我在class中有一个方法,其结构如下:
class TestClass(object):
...
def __init__(self, ...)
...
self.var1 = ...
self.var2 = ...
...
...
def xyz(self, other)
if isinstance(other, TestClass):
...
self.var1 = ...
...
else:
...
self.var2 = ...
...
现在假设我想写另一个 class NewTestClass
继承自 TestClass
(即 class NewTestClass(TestClass): ...
)。
方法 xyz
的一个问题是它明确检查 other
变量是否是 TestClass
的实例并且它还引用实例的属性(即 self.var1
, self.var2
).
(a) 如何重写方法 xyz
以便在继承时(在 NewTestClass
中),if
语句的行为类似于 if isinstance(other, NewTestClass): ...
(我不不必在 NewTestClass
) 中重写方法 xyz
?
(b) 同样,假设我在 TestClass
中有另一个 method
引用 TestClass
中的 staticmethod
,例如:
@staticmethod
def abc(x):
...
val = ...
...
return val
def mnp(self, ...):
...
x1 = ...
self.var1 = TestClass.abc(x1)
...
此处,方法 mnp
使用 staticmethod
of TestClass
(即本例中的 TestClass.abc
)。我如何重写 TestClass.abc
,以便当 NewTestClass
继承 TestClass
时,它得到一个方法 mnp
将 self.var =
行视为等同于 self.var1 = NewTestClass.abc(x1)
(而且我不必在 NewTestClass
中重写方法 mnp
)?
你可以做一些丑陋的反射来让它工作,但这不是正确的做法。如果 classes 想自然地相互延伸 - 做,如果不是 - 不要。
就是说,您可以做的一件事是更改当前的实现,而不是分配一个 var - 调用另一个这样做的函数,并在每个 class 中实现此函数以修改正确的变量。
例如,更改:
def xyz(self, other)
if isinstance(other, TestClass):
...
self.var1 = ...
...
else:
...
self.var2 = ...
...
至:
def xyz(self, other)
if isinstance(other, TestClass):
...
self.modifyVar(value)
...
else:
...
self.var2 = ...
...
然后 class 您将实现:
def modifyVar(self, value):
self.var1 = value
在另一个 class 中,您将拥有:
def modifyVar(self, value):
self.var2 = value
这个答案涵盖了两种情况(静态和非静态函数)。
一)
def xyz(self, other):
if isinstance(other, self.__class__):
...
b) 您可以使用 self
:
def mnp(self, ...):
....
self.var1 = self.abc(...)
对于(a)部分,您需要检查other
是否是与self
相同的class的实例:
class TestClass(object):
def xyz(self, other):
if isinstance(other, self.__class__):
...
self.var1 = ...
...
else:
...
self.var2 = ...
...
通常认为 'pythonic' 尽可能避免 isinstance
这种逻辑。考虑使用 Python 的鸭子类型。以下示例不会完全满足您的需要,因为这两个属性都存在于您的 class 中。但是,如果您为实际代码选择了适当的异常,则此技术将起作用。
class TestClass(object):
def xyz(self, other):
try:
self.var1 = ... # The minimum code required to raise the exception
except AttributeError:
self.var2 = ...
else:
pass # Any other code if the exception is not raised
Python 的异常处理是轻量级的,旨在以这种方式使用。如果传入意外(可能尚未考虑),它会使您的代码更具弹性。
对于(b)部分,调用静态方法时不需要指定class。它可以在实例 (self
) 上调用。
class TestClass(object):
@staticmethod
def abc(x):
return x # Do something useful
def mnp(self, x):
self.var1 = self.abc(x)
现在,当您在派生的 class 中声明一个新的静态方法时,它将被正确调用:
class NewTestClass(TestClass):
@staticmethod
def abc(x):
return x * 2 # Do something else useful
a = NewTestClass()
a.mnp(1)
assert a.var1 == 2 # because NewTestClass.abc was called by mnp