python - 如何在 Python 的抽象类实现中使用 self?
问题描述
我正在开发一个使用 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'
。
我认为这是因为get_contents()
在 ImplementationOne 中需要self
,但未在抽象方法中指定。
所以,如果我改变:
@abstractmethod
def get_contents():
pass
至
@abstractmethod
def get_contents(self):
pass
但我得到同样的错误。
我尝试了很多组合,包括将self
每个出现的或作为参数get_contents
,并在抽象类中传递cls
给get_contents
- 但没有运气。
所以,几乎,我如何才能self
在抽象方法的某些实现中使用关键字(也称为访问属性),这在抽象类本身的类方法中调用。
另外,附带说明一下,如何self.sublinks
从 BaseClass 的所有实现中访问,同时在实现的每个实例中具有不同的值?
解决方案
这里有一些问题。一个是@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
在两个子类中获取属性。由于您是压倒一切__init__
的,因此ImplementationOne
您还需要调用父类__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)
推荐阅读
- microsoft-graph-api - 服务器任务/守护程序使用 MS Graph API 从 Sharepoint Online 读取 Excel 工作簿
- javascript - Firebase 存储不上传所有文件
- linux - 在 qemu 下运行的客户机中配置交换空间
- python - 如何通过 url 使用 python R&W 到谷歌表格
- c - 获取c中ascii字符组合的每个模式的数量
- azure-data-factory - 带有 TTL 的集成运行时对集群启动时间没有帮助
- vert.x - 集群 Vert.x 环境中的 SockJS 连接
- swift - 来自文件的快速图像数据 不允许操作
- vue.js - 在动态 Vue 3 App 中绑定 OG 标签的正确方法是什么?
- java - Android Studio SQLite 没有名为 TIME 的列