简体   繁体   English

如何正确编写抽象 class 及其子类以具有 getter/setter 行为?

[英]How do I correctly code an abstract class and its subclasses to have getter/setter behavior?

In Python (3.11) I have this abstract class:在 Python (3.11) 中,我有这个摘要 class:

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

I create this subclass:我创建了这个子类:

class ScienceFiction(BookPrototype):

    def title(self, val):
        print("this never gets called without decorator")

    def __init__(self):
        pass

    def clone(self):
        return deepcopy(self)

And use it this way:并以这种方式使用它:

science1 = ScienceFiction()
science1.title = "From out of nowhere"
science2 = science1.clone()
print(science2.title)
science2.title = "New title"
print(science2.title)
print(science1.title)

This code does exactly what I want, that is it creates an instance of ScienceFiction class, it clones it, it prints the title of the cloned object and again the title of the first one.这段代码正是我想要的,它创建了一个ScienceFiction class 的实例,它克隆了它,它打印了克隆的 object 的标题和第一个的标题。 So, my prints here are "From out of nowhere", "New Title", "From out of nowhere".所以,我这里的版画是“不知从何而来”、“新标题”、“不知从何而来”。

Problem is when, followingthe docs , I add the @BookPrototype.title.setter decorator to the title setter, this way:问题是,按照文档,我将@BookPrototype.title.setter装饰器添加到标题设置器中,这样:

@BookPrototype.title.setter
    def title(self, val):
        print("this gets called now")
    

In this case the print inside the title method works, BUT I can't assign any value, so that the code prints three None.在这种情况下,title 方法中的 print 有效,但我无法分配任何值,因此代码打印了三个 None。

What am doing wrong?做错了什么? How do I correctly code an abstract class and its subclasses to have getter/setter behavior?如何正确编写抽象 class 及其子类以具有 getter/setter 行为?

The title value should be stored in a variable.标题值应存储在变量中。 For instance it could be stored in self._title in the base class. I think what you are looking for is something like: from abc import ABCMeta, abstractmethod from copy import deepcopy例如,它可以存储在基数self._title的 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

When you remove the decorator @BookPrototype.title.setter as in:当您删除装饰器@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)

setting the variable title with a string just override the method with a str object. This can be seen with the following:使用字符串设置变量title只需使用str object 覆盖方法。这可以通过以下方式看到:

science = ScienceFiction()
print(type(getattr(science, 'title')))
science.title = "From out of nowhere"
print(type(getattr(science, 'title')))

# <class 'method'>
# <class 'str'>  

Note that in python you can dynamically add / modify / delete attributes.注意python可以动态添加/修改/删除属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM