Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何仅将属性和方法的访问限制为枚举成员?_Python_Enums_Properties - Fatal编程技术网

Python 如何仅将属性和方法的访问限制为枚举成员?

Python 如何仅将属性和方法的访问限制为枚举成员?,python,enums,properties,Python,Enums,Properties,我计划在代码中使用一个非正统的Enum,但是我遇到了一个问题,当Enum被错误使用时,我需要我的属性抛出一个错误,但是,它不是抛出异常,而是输出我的属性的地址 我希望我的代码如何工作: 当用户写入Enum.MEMBER.text时,返回Enum.MEMBERalt text 当用户写入Enum.text时,抛出一个错误 下面是代码片段 类MyEnum(枚举): @财产 def文本(自我): 如果isinstance(self.\u value,MyCapsule):返回self.\u val

我计划在代码中使用一个非正统的
Enum
,但是我遇到了一个问题,当
Enum
被错误使用时,我需要我的属性抛出一个错误,但是,它不是抛出异常,而是输出我的属性的地址

我希望我的代码如何工作:

  • 当用户写入
    Enum.MEMBER.text
    时,返回
    Enum.MEMBER
    alt text
  • 当用户写入
    Enum.text
    时,抛出一个错误
下面是代码片段

类MyEnum(枚举):
@财产
def文本(自我):
如果isinstance(self.\u value,MyCapsule):返回self.\u value\u.text
引发异常('您没有使用枚举!')
一无所获
@财产
def值(自身):
如果isinstance(self.\u value,MyCapsule):返回self.\u value
引发异常('您没有使用枚举!')
一无所获
MyCapsule类别:
定义初始化(自身、值、文本、更多数据):
self.\u值,self.\u文本(值,文本)
@财产
定义文本(self):返回self.\u文本_
@财产
定义值(self):返回self.\u值_
类CustomData(MyEnum):
一个=我的胶囊(1,'1','Lorem')
二=我的胶囊(2,'2','Ipsum')
TRI=MyCapsule(3,'TRI','Loipsum')
A=CustomData.ONE
B=自定义数据
打印(A.text,A.value,sep='|')
打印(B.text,B.value,sep='|')
输出为:

One | 1
<property object at 0x0000016CA56DF0E8> | <property object at 0x0000016CA56DF278>

是否有解决此问题的方法,或者我不应该以这种方式开始编写我的
Enum

自定义描述符将完成以下操作:

class property_only(object):
    #
    def __init__(self, func):
        self.func = func
    #
    def __get__(self, instance, cls):
        if instance is None:
            raise Exception('You are not using an Enum!')
        else:
            return self.func(instance)
    #
    def __set__(self, instance, value):
        # raise error or set value here
        pass
然后更改基本枚举以使用它:

class MyEnum(Enum):
    @property_only
    def text(self):
        return self._value_.text
    @property_only
    def value(self):
        return self._value_.value

class MyCapsule:
    def __init__(self, value, text, more_data):
        self._value_, self._text_ = (value, text)

class CustomData(MyEnum):
    ONE = MyCapsule(1, 'One', 'Lorem')
    TWO = MyCapsule(2, 'Two', 'Ipsum')
    TRI = MyCapsule(3, 'Tri', 'Loipsum')
在使用中:

>>> CustomData.text
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __get__
Exception: You are not using an Enum!
>>> CustomData.ONE
<CustomData.ONE: 1>

>>> CustomData.ONE.value
1

>>> CustomData.ONE.text
'One'

>>> CustomData.ONE.name
'ONE'

>>> CustomData.text
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __get__
Exception: You are not using an Enum!

>>> CustomData.value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __get__
Exception: You are not using an Enum!
解决方案是将
MyCapsule
直接合并到
CustomData

from enum import Enum

class property_only(object):
    #
    def __init__(self, func):
        self.func = func
    #
    def __get__(self, instance, cls):
        if instance is None:
            raise Exception('You are not using an Enum!')
        else:
            return self.func(instance)
    #
    def __set__(self, instance, value):
        # raise error or set value here
        pass

class CustomData(Enum):
    #
    ONE = 1, 'One', 'Lorem'
    TWO = 2, 'Two', 'Ipsum'
    TRI = 3, 'Tri', 'Loipsum'
    #
    def __new__(cls, value, text, more_data):
        member = object.__new__(cls)
        member._value_ = value
        member._text_ = text
        # ignoring more_data for now...
        return member
    #
    @property_only
    def text(self):
        return self._text_
    #
    @property_only
    def value(self):
        return self._value_
在使用中:

>>> CustomData.text
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __get__
Exception: You are not using an Enum!
>>> CustomData.ONE
<CustomData.ONE: 1>

>>> CustomData.ONE.value
1

>>> CustomData.ONE.text
'One'

>>> CustomData.ONE.name
'ONE'

>>> CustomData.text
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __get__
Exception: You are not using an Enum!

>>> CustomData.value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __get__
Exception: You are not using an Enum!
>>CustomData.ONE
>>>CustomData.ONE.value
1.
>>>CustomData.ONE.text
“一个”
>>>CustomData.ONE.name
“一个”
>>>CustomData.text
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第8行,在__
例外:您没有使用枚举!
>>>CustomData.value
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第8行,在__
例外:您没有使用枚举!


披露:我是《和图书馆》、《和图书馆》的作者。

主要问题是你为什么需要它。顺便说一句,这是不可能的。@OlvinRoght基本上我计划使用这个枚举来“分类”我的数据,并将其用于我的GUI界面。很难用语言来解释。老实说,这个错误在我的代码中并不是什么大问题,每次看到可能的错误,我都会感到恼火。为什么不可能呢?我在想,如果我能检查
cls.\u value.
类型,在某种程度上应该是可能的?你不能阻止在代码中使用类名,也许你可以通过使用不同代理的一些“黑客”来实现,但我不能确定一个原因。@OlvinRoght我真的不必在代码中使用类,我可以使用tuple或者创建一个自定义IntEnum之类的东西,但是我更喜欢使用class来代替它。这就是我一直在寻找的东西!这是一个很大的帮助:)间接部分不是一个大问题,但它是一个很好的参考,不知何故,在看到这个答案之前,我做了一些类似的事情。哈哈。我也在研究你的
Enum
源代码,发现了另一个解决方案,使用
DynamicClassAttribute
描述符。这是个好主意吗?太糟糕了,我的IDE(VS代码)没有将它们识别为属性。@ZombieChibiXD:Yes,DynamicClassAttribute也可以工作。