首页 > 解决方案 > 处理只读用户输入的面向对象的方式

问题描述

我正在制作一个简单的命令行游戏,但不确定如何在 Python 中为只读用户输入建模。

现在,我正在考虑声明一个名为 ABCInput并将其子类化:

import abc


class Input(abc.ABC):
    @abc.abstractmethod
    def is_valid(self, *args, **kwargs):
        pass

    @abc.abstractmethod
    def pop(self):
        pass


class NameInput(Input):
    def __init__(self, name):
        self._name = name

    def is_valid(self, *args, **kwargs):
        pass

    def pop(self):
        return self._name

我想出的另一种方法是使用@property装饰器:

import abc


class Input(abc.ABC):
    @abc.abstractmethod
    def is_valid(self, *args, **kwargs):
        pass

    @abc.abstractmethod
    def value(self, value, *args, **kwargs):
        pass


class NameInput(Input):
    def __init__(self, name):
        self._name = name

    def is_valid(self, *args, **kwargs):
        pass

    @property
    def value(self, value, *args, **kwargs):
        return self._name

有没有更好的方法来实现我的目标?如果是这样,它是什么?

供您参考,我的目标不仅仅是建立一个程序并运行,而是养成良好的编程习惯。请随意过于复杂并告诉我您在大型项目中更喜欢的方式(为了可伸缩性和可维护性)。

标签: pythonoopinputmodeling

解决方案


该名称.pop()几乎是为堆栈保留的。你不应该使用它,因为你在这里做的行为是不同的。

@property很好,但是你滥用了它。它应该是:

class NameInput(Input):
    def __init__(self, name):
        self._name = name

    def is_valid(self, *args, **kwargs):
        pass

    @property
    def value(self):
        return clean_data(self._name)

    @value.setter
    def value(self, value):
        self._name = value

第二个value功能是如果你想让你的value属性可设置。

您可以在此处找到更多信息:@property 装饰器如何工作?

该属性允许您对输入或输出进行一些深入的清理(如删除 HTML 注入,...)。我打电话clean_data()是为了这个例子,那里。

但也许,根据您的实际情况,您可能想要创建自己的描述符,以便您可以重用它们。例如,这就是在 ORM 中发生的事情。更多信息:https ://docs.python.org/3.7/howto/descriptor.html

就像,在 django ORM(例如http://www.effectivedjango.com/orm.htmlmodels.CharField )中,所有这些models.XxxXxx都是描述符。您可能想阅读更多文档(上面的链接)或检查这些项目的源代码。你可能会找到灵感:-)。

祝你好运!


推荐阅读