在Python(3.11)中我有这个抽象类:
from abc import ABCMeta, abstractmethod
from copy import deepcopy
class BookPrototype(metaclass=ABCMeta):
@property
def title(self):
pass
@title.setter
@abstractmethod
def title(self, val):
pass
@abstractmethod
def clone(self):
pass
我创建这个子类:
class ScienceFiction(BookPrototype):
def title(self, val):
print("this never gets called without decorator")
def __init__(self):
pass
def clone(self):
return deepcopy(self)
并以这种方式使用它:
science1 = ScienceFiction()
science1.title = "From out of nowhere"
science2 = science1.clone()
print(science2.title)
science2.title = "New title"
print(science2.title)
print(science1.title)
这段代码完全符合我的要求,即它创建
ScienceFiction
类的实例,克隆它,打印克隆对象的标题,并再次打印第一个对象的标题。所以,我这里的版画是“不知从何而来”,“新标题”,“不知从何而来”。
问题是,按照文档,我将
@BookPrototype.title.setter
装饰器添加到标题设置器,这样:
@BookPrototype.title.setter
def title(self, val):
print("this gets called now")
在这种情况下,标题方法中的 print 可以工作,但我无法分配任何值,因此代码打印三个 None。
我做错了什么?如何正确编码抽象类及其子类以具有 getter/setter 行为?
标题值应存储在变量中。例如,它可以存储在基类的
self._title
中。
我想你正在寻找的是这样的:
from abc import ABCMeta, abstractmethod
from copy import deepcopy
class BookPrototype(metaclass=ABCMeta):
def __init__(self):
self._title: str = ""
@property
def title(self):
return self._title
@title.setter
@abstractmethod
def title(self, val):
...
@abstractmethod
def clone(self):
...
class ScienceFiction(BookPrototype):
@BookPrototype.title.setter
def title(self, val):
self._title = val
def clone(self):
return deepcopy(self)
science1 = ScienceFiction()
science1.title = "From out of nowhere"
science2 = science1.clone()
print(science2.title)
science2.title = "New title"
print(science2.title)
print(science1.title)
# From out of nowhere
# New title
# From out of nowhere
当您删除装饰器时
@BookPrototype.title.setter
,如下所示:
class ScienceFiction(BookPrototype):
def title(self, val):
print("this never gets called without decorator")
def __init__(self):
pass
def clone(self):
return deepcopy(self)
使用字符串设置变量
title
只需使用 str
对象覆盖该方法即可。这可以通过以下内容看出:
science = ScienceFiction()
print(type(getattr(science, 'title')))
science.title = "From out of nowhere"
print(type(getattr(science, 'title')))
# <class 'method'>
# <class 'str'>
注意,在Python中你可以动态添加/修改/删除属性。