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
alt textEnum.MEMBER
- 当用户写入
时,抛出一个错误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
也可以工作。