Skip to content

Commit 3f819e7

Browse files
authored
Merge pull request #2874 from ales-erjavec/variable-type-predicates
[ENH] Variable: Simplify the is_{discrete,continuous,...} implementation
2 parents 60f3ece + 2636957 commit 3f819e7

File tree

1 file changed

+41
-31
lines changed

1 file changed

+41
-31
lines changed

Orange/data/variable.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,28 @@ def __new__(cls, name, bases, attrs):
238238
return obj
239239

240240

241+
class _predicatedescriptor(property):
242+
"""
243+
A property that behaves as a class method if accessed via a class
244+
>>> class A:
245+
... foo = False
246+
... @_predicatedescriptor
247+
... def is_foo(self):
248+
... return self.foo
249+
...
250+
>>> a = A()
251+
>>> a.is_foo
252+
False
253+
>>> A.is_foo(a)
254+
False
255+
"""
256+
def __get__(self, instance, objtype=None):
257+
if instance is None:
258+
return self.fget
259+
else:
260+
return super().__get__(instance, objtype)
261+
262+
241263
class Variable(Reprable, metaclass=VariableMeta):
242264
"""
243265
The base class for variable descriptors contains the variable's
@@ -357,6 +379,22 @@ def is_primitive(cls, var=None):
357379
to_check = cls if var is None else type(var)
358380
return issubclass(to_check, (DiscreteVariable, ContinuousVariable))
359381

382+
@_predicatedescriptor
383+
def is_discrete(self):
384+
return isinstance(self, DiscreteVariable)
385+
386+
@_predicatedescriptor
387+
def is_continuous(self):
388+
return isinstance(self, ContinuousVariable)
389+
390+
@_predicatedescriptor
391+
def is_string(self):
392+
return isinstance(self, StringVariable)
393+
394+
@_predicatedescriptor
395+
def is_time(self):
396+
return isinstance(self, TimeVariable)
397+
360398
def repr_val(self, val):
361399
"""
362400
Return a textual representation of variable's value `val`. Argument
@@ -430,6 +468,9 @@ def copy(self, compute_value):
430468
return var
431469

432470

471+
del _predicatedescriptor
472+
473+
433474
class ContinuousVariable(Variable):
434475
"""
435476
Descriptor for continuous variables.
@@ -1011,34 +1052,3 @@ def to_val(self, s):
10111052
return self.parse(s)
10121053
else:
10131054
return super().to_val(s)
1014-
1015-
1016-
class _TypeIndicatorDescriptor:
1017-
"""
1018-
Descriptor that can be used on classes and on instances.
1019-
1020-
On an instance, the descriptor is used as a property of a variable,
1021-
e.g. `var.is_discrete`.
1022-
1023-
As a class attribute, the descriptor returns a predicate that can
1024-
be called as `Variable.is_discrete(var)` or, for a more common use,
1025-
`filter(Variable.is_discrete, domain)`.
1026-
"""
1027-
def __init__(self, atype):
1028-
def __check_type(instance):
1029-
return isinstance(instance, atype)
1030-
1031-
self.check_type = __check_type
1032-
1033-
def __get__(self, instance, owner):
1034-
if instance is not None:
1035-
return self.check_type(instance)
1036-
else:
1037-
return self.check_type
1038-
1039-
# These properties of Variable require its subclasses, hence they have to
1040-
# inserted into the class later.
1041-
Variable.is_discrete = _TypeIndicatorDescriptor(DiscreteVariable)
1042-
Variable.is_continuous = _TypeIndicatorDescriptor(ContinuousVariable)
1043-
Variable.is_string = _TypeIndicatorDescriptor(StringVariable)
1044-
Variable.is_time = _TypeIndicatorDescriptor(TimeVariable)

0 commit comments

Comments
 (0)