[英]How can I use a child class' function attribute in the base class?
我有一个 python 类继承结构,其中大多数方法在基类中定义,而这些方法所依赖的大多数属性在子类中定义。
基类大致如下所示:
class Base(object):
__metaclass__ = ABCMeta
@abstractproperty
def property1(self):
pass
@abstractproperty
def property2(self):
pass
def method1(self):
print(self.property1)
def method2(self, val):
return self.property2(val)
而子类看起来像这样:
class Child(Base):
property1 = 'text'
property2 = function
其中function
是一个如下所示的函数:
def function(val):
return val + 1
显然上面的代码缺少细节,但结构反映了我真实代码的结构。
当我尝试在基类中使用method1
,一切都按预期工作:
>>> child = Child()
>>> child.method1()
'text'
但是,对method2
尝试相同的方法会引发错误:
>>> child = Child()
>>> child.method2(1) # expected 2
TypeError: method2() takes exactly 1 argument (2 given)
第二个传递的参数是Child
类本身。
我想知道是否有办法避免在调用method2
时传递第二个Child
参数。
我发现的一种解决方法是在基类中定义一个抽象方法,然后在子类中构建该函数,如下所示:
class Base(object):
__metaclass__ = ABCMeta
@abstractproperty
def property1(self):
pass
@abstractmethod
def method2(self, val):
pass
def method1(self):
print(self.property1)
class Child(Base):
property1 = 'text'
def method2(self, val):
return function(val)
但是,我更希望这个方法存在于基类中。 有什么想法吗? 提前致谢!
方法隐式地接收self
作为第一个参数,即使它似乎没有被传递。 例如:
class C:
def f(self, x):
print(x)
Cf
有两个参数,但你通常只用一个来调用它:
c = C()
c.f(1)
这样做的方式是,当您访问cf
时,会创建一个“绑定”方法,该方法隐式地将c
作为第一个参数。
如果您将外部函数分配给类并将其用作方法,也会发生同样的情况,就像您所做的那样。
在子类中实现方法的通常方法是在子类中显式执行,而不是在外部函数中执行,因此我会执行以下操作而不是您所做的:
class Child(Base):
property1 = 'text'
# instead of: property2 = function
def property2(self, val):
return val + 1
如果你真的想拥有property2 = function
的类(不知道为什么)和function
了之类的,那么你必须照顾self
:
class Child(Base):
property1 = 'text'
property2 = function
def function(self, val):
return val + 1
如果你想要以前的解决方案,但没有self
在function
:
class Child(Base):
property1 = 'text'
def property2(self, val):
return function(val)
def function(val):
return val + 1
使您的方法静态:
class Child(Base)
property2 = staticmethod(function)
正如 zvone 已经解释的那样, 绑定方法隐式接收self
作为第一个参数。
要创建绑定方法,您不一定需要在类主体中定义它。
这个:
def foo(self):
print("foo")
class Foo:
bar = foo
f = Foo()
print(f.bar)
将输出:
>>> <bound method foo of <__main__.Foo object at 0x014EC790>>
因此,分配给类属性的函数的行为就像普通的类方法一样,这意味着如果您将其作为f.bar()
调用,它将被视为绑定方法,而self
作为第一个参数隐式传递。
控制隐式传递给类方法的内容和内容,因为第一个参数通常由装饰器控制
@classmethod
:类本身作为第一个参数传递@staticmethod
:没有参数被隐式传递给方法所以你想要一个staticmethod
的行为,但由于你只是将一个已经定义的函数分配给一个类属性,你不能使用装饰器语法。
但是由于装饰器只是将函数作为参数并返回包装函数的普通函数,因此:
class Child(Base):
property2 = staticmethod(function)
等价于 (*):
class Child(Base):
@staticmethod
def property2():
function()
我建议对您的Base
类进行一些小的额外修改:
重命名property2
并将其标记为abstractproperty
property2
而不是abstractproperty
abstractstaticmethod
(**)。 这将帮助同事(最终是你自己)更好地理解子类中期望什么样的实现。
class Base(object):
__metaclass__ = ABCMeta
@abstractstaticmethod
def staticmethod1(self):
pass
(*) 好吧,或多或少。 前者实际上将function
分配给property2
,后者创建了一个新的静态方法,该方法委托给function
。
(**) abstractstaticmethod
自 Python 3.3 起已弃用,但由于您也在使用abstractproperty
我希望保持一致。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.