如何在 Python 中的抽象 class 实现中使用 self?

How to use self in an abstract class implementation in Python?

我正在做一个项目,在 Python 中使用抽象 classes(特别是 abc 模块)。

我有几个这个抽象的实现 class,它们有自己的构造函数,需要使用 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 class - 但运气不好。

所以,差不多,我怎样才能在抽象方法的某些实现中使用 self 关键字(又名访问属性),它在抽象 class 方法中调用48=]本身。

此外,附带说明一下,如何从 BaseClass 的所有实现中访问 self.sublinks,同时在每个实现实例中具有不同的值?

这里有一些错误。一个是 @classmethod 装饰器只应在需要在 class.

上调用时使用

示例:

class ImplementationOne:
    @classmethod
    def display(cls):
        print(f'The class name is {cls.__name__}.')

ImplementationOne.display()

名字self没有什么特别的。这只是每个人用来指代实例的东西。在 python 中,实例被隐式传递给 class 的第一个参数,除非你有一个 @classmethod 装饰器。在这种情况下,class 将作为第一个参数传递。

这就是您获得 TypeError 的原因。由于您在实例 test_one.display() 上调用该方法,因此您实际上是将其作为实例方法调用。由于您需要从其中访问实例方法 get_contents,这就是您想要的。作为 classmethod,您将无权访问 get_contents

这意味着您需要 ABC 和 ImplementationOne 才能将这些方法实现为实例方法。

因为它现在是 ABC 上的实例方法,所以它也应该是 ImplementationTwo 中的实例方法。

您的另一个问题是如何将 self.sublinks 作为两个子 class 中的属性。 由于您正在覆盖 ImplementationOne 中的 __init__,因此您还需要调用父 class 的 __init__。您可以通过使用 super() 调用 Super 或 Base class 的方法来做到这一点。

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)