J'obtiens les erreurs suivantes de pylint lors de l'utilisation des membres "value" et "equals" d'une classe enum: "code": "no-member" "message": "L'instance de 'Tuple' n'a pas de membre 'value'" Versions: pylint 2.3.1 astroid 2.2.5 Python 3.6.3
Le code est exécuté comme prévu. Je me demande simplement s'il y a quelque chose que je fais mal (je ne suis pas un pro python), ou s'il existe un moyen plus "Pythonic" pour obtenir le même résultat:
from enum import Enum
class DefaultEnum(Enum):
def __new__(self,val,_name,_type):
obj = object.__new__(self)
obj._value_ = val
obj._publicName = _name
obj._type = _type
return obj
def __str__(self):
return self._publicName
def equals(self,_string):
return _string == str(self)
class GlobalEnum(DefaultEnum):
TRUE = 0,'True',str()
FALSE = 1,'False',str()
GlobalEnum.TRUE.value
>> 0
GlobalEnum.TRUE.equals('True')
>> True
repr(GlobalEnum.TRUE)
>> <GlobalEnum.TRUE: 0>
J'utilise actuellement le commentaire "# pylint: disable = no-member" pour désactiver l'avertissement, mais je préférerais ne pas le faire ... Il en va de même pour la liste blanche de la classe car je voudrais toujours que pylint signale d'autres résultats.
Pour répondre à votre question principale:
pylint
ne reconnaît pas les attributs créés dynamiquement, etEnum
est "spécial" dans un nombre de façons , l'un d'eux étant que les membres d'un Enum sont en fait des instances de la classe enum
: from enum import Enum
class MyEnum(Enum):
val1 = 0
print(type(MyEnum.val1)) # <enum 'MyEnum'>
class MyClass:
val1 = 0
print(type(MyClass.val1)) # <class 'int'>
Autrement dit, lorsque vous définissez TRUE
dans votre classe GlobalEnum
, Python convertit TRUE
en une instance de GlobalEnum
, mais pylint ne comprend pas cela, et comme il semble que GlobalEnum.TRUE
se voit attribuer une valeur Tuple, pylint pense que c'est un Tuple, qui n'a pas de membre "value".
Pour répondre s'il y a une façon plus "Pythonique" d'obtenir le même résultat, je ne suis pas sûr de ce que vous essayez d'accomplir, mais il semble qu'il y ait des choses étranges que vous faites. Par exemple:
__new__()
obtient passé une classe comme premier argument, mais vous l'appelez "self", qui par (presque-) la convention universelle fait référence à une instance , ce qui est très déroutant à lire. Typiquement, on l'appellerait cls
.
Les traits de soulignement simples ("_name
", "_type
") Par convention sont généralement utilisés pour désigner les membres "privés", donc cela va être déroutant pour la plupart des lecteurs de les utiliser dans les signatures de fonction. Si vous souhaitez utiliser un mot réservé comme nom de paramètre, une convention courante consiste à utiliser un trait de soulignement de fin (par exemple, "type_
", "exec_
").
Je ne sais pas ce que vous essayez d'accomplir avec votre attribut "_type
", Mais pour le moment, GlobalEnum.TRUE
Et GlobalEnum.FALSE
Renverront une chaîne vide comme leur _type
, Car str()
renvoie une instance de chaîne et sans argument, la chaîne sera vide. Si vous souhaitez qu'il renvoie le type str
, vous devez le définir sur str
(sans les parenthèses).
Je pense ce que vous essayez de faire est de créer une énumération dont les valeurs seront évaluées à True par rapport à un int ou à une chaîne que vous spécifiez dans la définition. Dans ce cas, au lieu d'une méthode equals()
définie par l'utilisateur (que vous oublierez presque certainement à un moment donné), vous pouvez remplacer la méthode magique __eq__()
intégrée afin que vous pouvez utiliser à la place l'opérateur ==
habituel:
from enum import Enum
class BaseEnum(Enum):
def __init__(self, int_value, str_value):
self._value_ = int_value
self.str_value = str_value
def __eq__(self, other):
return other == self.value or other == self.str_value
class MyEnum(BaseEnum):
TRUE = 0, 'True'
FALSE = 1, 'False'
print(MyEnum.TRUE == 0) # True
print(MyEnum.TRUE == 'True') # True
a = MyEnum.TRUE
print(a == MyEnum.TRUE) # True
print(MyEnum.TRUE.value) # 0
print(MyEnum.TRUE.str_value) # 'True'
[Notez que str_value
Ci-dessus n'est qu'une propriété de classe régulière, ce qui signifie qu'elle peut être définie. Pour le rendre en lecture seule, vous pouvez utiliser un décorateur de propriété sans setter.]