[英]How to use self in an abstract class implementation in Python?
I'm working on a project using abstract classes in Python (specifically, the abc module).我正在使用 Python (特别是 abc 模块)中的抽象类来开发一个项目。
I have a few implementations of this abstract class, which have their own constructors and need to use self
.我有这个抽象 class 的一些实现,它们有自己的构造函数,需要使用self
。
This is what my code looks like, but simplified:这是我的代码的样子,但经过简化:
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()
When I run this, however, I get the error TypeError: get_contents() missing 1 required positional argument: 'self'
.但是,当我运行它时,我收到错误TypeError: get_contents() missing 1 required positional argument: 'self'
。
I figured that this is because get_contents()
in ImplementationOne takes self
, but it's not specified in the abstract method.我认为这是因为 ImplementationOne 中的get_contents()
采用self
,但未在抽象方法中指定。
So, if I changed:所以,如果我改变:
@abstractmethod
def get_contents():
pass
to至
@abstractmethod
def get_contents(self):
pass
But I get the same error.但我得到同样的错误。
I've tried many combinations, including putting self
as an argument to every occurrence or get_contents
, and passing in cls
to get_contents
in the abstract class - but no luck.我尝试了许多组合,包括将self
作为每次出现或get_contents
的参数,并将cls
传递给抽象get_contents
中的 get_contents - 但没有运气。
So, pretty much, how can I use the self
keyword (aka access attributes) in only some implementations of an abstract method, that's called within a class method in the abstract class itself.所以,几乎,我如何才能在抽象方法的某些实现中使用self
关键字(又名访问属性),这在抽象 class 本身的 class 方法中调用。
Also, on a side note, how can I access self.sublinks
from within all implementations of BaseClass, while having its values different in each instance of an implementation?另外,附带说明一下,如何从 BaseClass 的所有实现中访问self.sublinks
,同时在实现的每个实例中具有不同的值?
There are a few things wrong here.这里有一些问题。 One is that the @classmethod
decorator should only be used when you need it to be called on a class.一个是@classmethod
装饰器应该只在你需要在 class 上调用它时使用。
Example:例子:
class ImplementationOne:
@classmethod
def display(cls):
print(f'The class name is {cls.__name__}.')
ImplementationOne.display()
There is nothing special about the name self
. self
这个名字没有什么特别之处。 It's just what is used by everyone to refer to the instance.这只是大家用来指代实例的东西。 In python the instance is implicitly handed to the first argument of the class unless you have a @classmethod
decorator.在 python 中,实例隐式传递给 class 的第一个参数,除非您有@classmethod
装饰器。 In that case the class is handed as the first argument.在这种情况下, class 作为第一个参数传递。
That is why you are getting the TypeError
.这就是你得到TypeError
的原因。 Since you are calling the method on the instance test_one.display()
you are essentially calling it as an instance method.由于您在实例test_one.display()
上调用该方法,因此您实际上是在将其作为实例方法调用。 Since you need to access the instance method get_contents
from within it that is what you want.由于您需要从其中访问实例方法get_contents
,这就是您想要的。 As a classmethod
you wouldn't have access to get_contents
.作为一个类方法,您将get_contents
classmethod
That means you need both the ABC and ImplementationOne
to have those methods implemented as instance methods.这意味着您需要 ABC 和ImplementationOne
才能将这些方法实现为实例方法。
Since it is now an instance method on the ABC it also should be an instance method in ImplementationTwo
.由于它现在是 ABC 上的实例方法,因此它也应该是ImplementationTwo
中的实例方法。
Your other question was how to get self.sublinks
as an attribute in both subclasses.您的另一个问题是如何将self.sublinks
作为两个子类中的属性。 Since your are overriding __init__
in ImplementationOne
you need to call the parent class's __init__
as well.由于您在ImplementationOne
中覆盖了__init__
,因此您还需要调用父类的__init__
。 You can do this by using super()
to call the Super or Base class's methods.您可以通过使用super()
调用 Super 或 Base 类的方法来做到这一点。
class ImplementationOne(BaseClass):
def __init__(self, url):
self.url = url
super().__init__()
Full working code:完整的工作代码:
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.