I am getting the following errors from pylint when using the members "value" and "equals" from an enum class: "code": "no-member" "message": "Instance of 'tuple' has no 'value' member" Versions: pylint 2.3.1 astroid 2.2.5 Python 3.6.3
The code is executed as expected. I am just wondering if there might be something I am doing wrong (I am not a pro python programmer), or if there is a more "pythonic" way to achieve the same result:
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>
I am currently using the "# pylint: disable=no-member" comment to disable the warning, but I would prefer not to do this... The same goes for white-listing the class as I still would like pylint to report other findings.
The error nodes.py:17:24: E1101: Instance of 'tuple' has no '__name' member (no-member) should not appear for the tuple of Node s. pylint should treat the sum of 2 tuples as a tuple and not as a sequence of tuples.
That is, when you set TRUE in your GlobalEnum class, Python is converting TRUE into an instance of GlobalEnum, but pylint doesn't understand this, and since it looks like GlobalEnum.TRUE is being assigned a tuple value, pylint thinks it's a tuple, which has no "value" member.
In this case Pylint will give you an error that y is not a member of A . Automating the finding of such bugs in your tooling is very useful. However since Python is so dynamic there's a whole bunch of ways in which you can dynamically define members of a class, and Pylint won't always catch these.
However since Python is so dynamic there's a whole bunch of ways in which you can dynamically define members of a class, and Pylint won't always catch these. Pylint is smart enough to not emit any errors in this particular case, which is correct since this program will run:
To answer your main question:
pylint
doesn't recognize dynamically-created attributes, andEnum
is "special" in a number of ways, one of them being that an Enum's members are actually instances of the enum
class: 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'>
That is, when you set TRUE
in your GlobalEnum
class, Python is converting TRUE
into an instance of GlobalEnum
, but pylint doesn't understand this, and since it looks like GlobalEnum.TRUE
is being assigned a tuple value, pylint thinks it's a tuple, which has no "value" member.
To answer if there's a more "pythonic" way to achieve the same result, I'm not sure what you're trying to accomplish, but it looks like there are some weird things you're doing. For example:
__new__()
gets passed a class as its first argument, but you're calling it "self," which by (near-)universal convention refers to an instance, which is very confusing to read. Typically one would call it cls
.
Single leading underscores ("_name
", "_type
") by convention are usually used to denote "private" members, so it's going to be confusing to most readers to use them in function signatures. If you want to use a reserved word as a parameter name, a common convention is to use a trailing underscore (e.g., "type_
", "exec_
").
I'm not sure what you're trying to accomplish with your "_type
" attribute, but right now both GlobalEnum.TRUE
and GlobalEnum.FALSE
will return an empty string as their _type
, because str()
returns a string instance, and without args the string will be empty. If you want it to return the str
type, you should set it to str
(without the parentheses).
I think what you're trying to do is to create an enum whose values will evaluate to True when compared against either an int or a string that you specify in the definition. In that case, instead of a user-defined equals()
method (which you'll almost certainly forget to use at some point), you can override the built-in __eq__()
magic method so that you can use the usual ==
operator instead:
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'
[Note that str_value
above is just a regular class property, meaning it can be set. To make it read-only, you can use a property decorator without a setter.]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With