如何在 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'

我认为这是因为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,同时在每个实现实例中具有不同的值?

解决方法

这里有一些错误。一个是 @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)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...