Given an Enum
object that cannot be modified, and a custom Query
class that should generate a compilation of the Enum
values given different arguments:
from enum import Enum
class Fields(Enum):
a = ["hello", "world"]
b = ["foo", "bar", "sheep"]
c = ["what", "the"]
d = ["vrai", "ment", "cest", "vrai"]
e = ["foofoo"]
class Query:
def __init__(self, a=True, b=True, c=False, d=False, e=False):
self.query_fields = set()
self.query_fields.update(Fields.a.value) if a else None
self.query_fields.update(Fields.b.value) if b else None
self.query_fields.update(Fields.c.value) if c else None
self.query_fields.update(Fields.d.value) if d else None
self.query_fields.update(Fields.e.value) if e else None
It's possible to get a custom set of query_fields
, as such:
[out]:
>>> x = Query()
>>> x.query_fields
{'bar', 'foo', 'hello', 'sheep', 'world'}
>>> x = Query(e=True)
>>> x.query_fields
{'bar', 'foo', 'foofoo', 'hello', 'sheep', 'world'}
Question: In the Query
initialization function, we had to iterate through each class argument and do something like self.query_fields.update(Fields.a.value) if a else None
, are there other ways to achieve the same behavior and output of Query().query_fields
without hard-coding each argument?
The __str__() method is called by str(object) and the built-in functions format() and print() and returns the informal string representation of the object. Now you can get the value of the enum directly, without accessing the value attribute on the enum member. You can also use square brackets to access enum members.
Enum is a class in python for creating enumerations, which are a set of symbolic names (members) bound to unique, constant values. The members of an enumeration can be compared by these symbolic anmes, and the enumeration itself can be iterated over.
An enum is defined using the enum keyword, directly inside a namespace, class, or structure. All the constant names can be declared inside the curly brackets and separated by a comma. The following defines an enum for the weekdays. Above, the WeekDays enum declares members in each line separated by a comma.
An enumeration type (or enum type) is a value type defined by a set of named constants of the underlying integral numeric type.
For a more general solution, see below; for a solution for Fields
specifically and which doesn't need *args
(or *members
as the case may be...) check out Tomer Shetah's answer.
General Solution
To make Query
more generalized and usable with other Enums, I would specify which Field
members you wanted:
class Query:
#
def __init__(self, *members):
self.query_fields = set()
for member in members:
self.query_fields.update(member.value)
and in use:
>>> x = Query()
>>> x.query_fields
set()
>>> y = Query(Fields.a, Fields.c)
>>> y.query_fields
{'world', 'the', 'hello', 'what'}
If your defaults are common, you can put them in another variable and use that:
>>> fields_default = Fields.a, Fields.b
>>> z = Query(*fields_default)
>>> z.query_fields
{'foo', 'bar', 'world', 'hello', 'sheep'}
You can iterate over Fields to get all the elements, and then use that .name or .value to get the respective attribute.
from enum import Enum
class Fields(Enum):
a = ["hello", "world"]
b = ["foo", "bar", "sheep"]
c = ["what", "the"]
d = ["vrai", "ment", "cest", "vrai"]
e = ["foofoo"]
class Query:
defaults = [True, True, False, False, False]
def __init__(self, **kwargs):
self.query_fields = set()
for attr, default in zip(Fields, self.defaults):
if attr.name in kwargs:
if kwargs[attr.name]:
self.query_fields.update(attr.value)
elif default:
self.query_fields.update(attr.value)
x = Query()
print(x.query_fields)
x = Query(a=False, e=True)
print(x.query_fields)
Note that the number of elements in fields and their order is hardcoded in Query.defaults, but I dont think it makes sense for that not to be the case.
After reading Get a list/tuple/dict of the arguments passed to a function? I figured out it can be achieved without using *args
.
There is the short version:
class Query:
def __init__(self, a=True, b=True, c=False, d=False, e=False):
self.query_fields = set()
local_variables = locals()
[self.query_fields.update(Fields[local].value) for local in local_variables if local_variables[local] is True]
or the more verbose option:
class Query:
def __init__(self, a=True, b=True, c=False, d=False, e=False):
self.query_fields = set()
local_variables = locals()
for local in local_variables:
if local_variables[local] is True:
self.query_fields.update(Fields[local].value)
The output in both implementations for:
x = Query()
print(x.query_fields)
is:
{'hello', 'foo', 'bar', 'sheep', 'world'}
and for:
x = Query(e = True)
print(x.query_fields)
is:
{'foo', 'hello', 'sheep', 'foofoo', 'bar', 'world'}
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