如何在 Python 的抽象类实现中使用 self?
Posted
技术标签:
【中文标题】如何在 Python 的抽象类实现中使用 self?【英文标题】:How to use self in an abstract class implementation in Python? 【发布时间】:2021-04-30 05:44:06 【问题描述】:我正在开发一个使用 Python 中的抽象类(特别是 abc 模块)的项目。
我有几个这个抽象类的实现,都有自己的构造函数,需要使用self
。
这是我的代码的样子,但经过简化:
from abc import ABC, abstractmethod
class BaseClass(ABC):
def __init__(self):
self.sublinks = [] # not meant to be passed in, that's why it isn't an argument in __init__
@classmethod
def display(cls):
print(cls.get_contents())
@abstractmethod
def get_contents():
pass
class ImplementationOne(Base):
def __init__(self, url):
self.url = url
def get_contents(self):
return "The url was: " + url
class ImplementationTwo(Base):
def get_contents():
return "This does not need a url"
test_one = ImplementationOne("https://google.com")
test_two = ImplementationTwo()
test_one.display()
但是,当我运行它时,我收到了错误 TypeError: get_contents() missing 1 required positional argument: 'self'
。
我认为这是因为 ImplementationOne 中的get_contents()
采用了self
,但在抽象方法中没有指定。
所以,如果我改变了:
@abstractmethod
def get_contents():
pass
到
@abstractmethod
def get_contents(self):
pass
但我得到了同样的错误。
我尝试了很多组合,包括将self
作为每次出现的参数或get_contents
,并在抽象类中将cls
传递给get_contents
- 但没有运气。
那么,我如何才能仅在抽象方法的某些实现中使用self
关键字(也称为访问属性),该方法在抽象类本身的类方法中调用。
另外,附带说明一下,如何在 BaseClass 的所有实现中访问 self.sublinks
,同时在每个实现实例中具有不同的值?
【问题讨论】:
this 有帮助吗? 【参考方案1】:这里有一些问题。一个是 @classmethod
装饰器应该只在你需要在类上调用它时使用。
例子:
class ImplementationOne:
@classmethod
def display(cls):
print(f'The class name is cls.__name__.')
ImplementationOne.display()
self
这个名字没有什么特别之处。这只是大家用来指代实例的东西。在 python 中,除非您有 @classmethod
装饰器,否则实例会隐式传递给类的第一个参数。在这种情况下,类作为第一个参数传递。
这就是您收到TypeError
的原因。由于您在实例test_one.display()
上调用该方法,因此您实际上是在将其作为实例方法调用。由于您需要从其中访问实例方法get_contents
,这就是您想要的。作为classmethod
,您将无权访问get_contents
。
这意味着您需要 ABC 和 ImplementationOne
才能将这些方法实现为实例方法。
既然它现在是 ABC 上的实例方法,它也应该是 ImplementationTwo
中的实例方法。
您的另一个问题是如何将self.sublinks
作为两个子类中的属性。
由于您在ImplementationOne
中覆盖__init__
,因此您还需要调用父类的__init__
。您可以通过使用super()
调用 Super 或 Base 类的方法来做到这一点。
class ImplementationOne(BaseClass):
def __init__(self, url):
self.url = url
super().__init__()
完整的工作代码:
from abc import ABC, abstractmethod
class BaseClass(ABC):
def __init__(self):
self.sublinks = []
def display(self):
print(self.get_contents())
@abstractmethod
def get_contents(self):
pass
class ImplementationOne(BaseClass):
def __init__(self, url):
self.url = url
super().__init__()
def get_contents(self):
return "The url was: " + self.url
class ImplementationTwo(BaseClass):
def get_contents(self):
return "This does not need a url"
test_one = ImplementationOne("https://google.com")
test_two = ImplementationTwo()
test_one.display()
test_two.display()
print(test_one.sublinks)
【讨论】:
以上是关于如何在 Python 的抽象类实现中使用 self?的主要内容,如果未能解决你的问题,请参考以下文章