我可以在Python3中限制对象,以便只允许我创建setter的属性吗?

mar*_*aft 11 oop inheritance python-3.x

我有一个叫做Node的东西.定义和定理都是一种节点,但只允许定义具有plural属性:

class Definition(Node):


    def __init__(self,dic):
        self.type = "definition"
        super(Definition, self).__init__(dic)
        self.plural = move_attribute(dic, {'plural', 'pl'}, strict=False)


    @property
    def plural(self):
        return self._plural

    @plural.setter
    def plural(self, new_plural):
        if new_plural is None:
            self._plural = None
        else:
            clean_plural = check_type_and_clean(new_plural, str)
            assert dunderscore_count(clean_plural)>=2
            self._plural = clean_plural


class Theorem(Node):


    def __init__(self, dic):
        self.type = "theorem"
        super().__init__(dic)
        self.proofs = move_attribute(dic, {'proofs', 'proof'}, strict=False)
        # theorems CANNOT have plurals:
        # if 'plural' in self:
        #   raise KeyError('Theorems cannot have plurals.')
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,定义有一个plural.setter,但定理没有.但是,代码

theorem = Theorem(some input)
theorem.plural = "some plural"
Run Code Online (Sandbox Code Playgroud)

运行得很好,没有错误.但我希望它引发错误.正如您所看到的,我尝试在显示的代码底部手动检查复数,但这只是一个补丁.我想阻止没有明确定义的任何属性的设置.这种事情的最佳做法是什么?


我正在寻找满足" 鸡肉"要求的答案:

我不认为这解决了我的问题.在你的两个解决方案中,我都可以附加代码t.chicken ='hi'; print(t.chicken),它打印出来没有错误.我不希望用户能够像鸡一样构成新的属性.

alf*_*sin -1

是的,您可以创建不能从类外部修改的私有成员。变量名称应以两个下划线开头:

\n\n
class Test(object):\n\n    def __init__(self, t):\n        self.__t = t\n\n\n    def __str__(self):\n        return str(self.__t)\n\nt = Test(2)\nprint(t) # prints 2\nt.__t = 3\n\nprint(t) # prints 2\n
Run Code Online (Sandbox Code Playgroud)\n\n

也就是说,尝试像我们所做的那样访问这样的变量t.__t = 3不会引发异常。

\n\n

实现所需行为的另一种方法是使用函数。这种方法需要使用函数符号“访问属性”,但如果这不打扰您,您可以得到您想要的。以下演示对值进行“硬编码”,但显然您可以Theorem()接受参数并使用它动态设置属性的值。

\n\n

演示:

\n\n
# -*- coding: utf-8 -*-\ndef Theorem():\n    def f(attrib):\n\n        def proofs():\n            return \'\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\'\n\n        def plural():\n            return \'\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\'\n\n        if attrib == \'proofs\':\n            return proofs()\n        elif attrib == \'plural\':\n            return plural()\n        else:\n            raise ValueError("Attribute [{}] doesn\'t exist".format(attrib))\n\n    return f\n\nt = Theorem()\nprint(t(\'proofs\'))\n\nprint(t(\'plural\'))        \n\nprint(t(\'wait_for_error\')) \n
Run Code Online (Sandbox Code Playgroud)\n\n

输出

\n\n
\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\xef\xa3\xbf\n\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\xe2\x97\x8a\nTraceback (most recent call last):\n  File "/Users/alfasi/Desktop/1.py", line 40, in <module>\n    print(t(\'wait_for_error\'))       \n  File "/Users/alfasi/Desktop/1.py", line 32, in f\n    raise ValueError("Attribute [{}] doesn\'t exist".format(attrib))\nValueError: Attribute [wait_for_error] doesn\'t exist\n
Run Code Online (Sandbox Code Playgroud)\n