0

I have subclassed the builtin Python list.

An empty list will evaluate to false in an if construct, but I want my subclass to evaluate to true.

Is there any dunder method available that I can override in my subclass to change this behavior?

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
Akilesh
  • 1,252
  • 1
  • 9
  • 16
  • 1
    See [this question](http://stackoverflow.com/questions/2233786/overriding-bool-for-custom-class); for [Python 2](http://docs.python.org/2/reference/datamodel.html#object.__nonzero__) and [Python 3](http://docs.python.org/3.3/reference/datamodel.html#object.__bool__). – DSM Jan 01 '14 at 07:22
  • I cannot understand what you problem you hope to solve by doing this. – Karl Knechtel Jan 01 '14 at 08:52
  • i had subclassed list for other reasons not just to make an empty list return True. It was just one of my necessities. – Akilesh Jan 01 '14 at 09:14

2 Answers2

1

According to the Python datamodel documentation, for the object.__nonzero__ method, this is doable (but it would violate the rule of least surprise, or principle of least astonishment):

Called to implement truth value testing and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1. When this method is not defined, len() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither len() nor nonzero(), all its instances are considered true.

Therefore hypothetically, we can check for len() == 0 and return True if it is, and then use the default for the boolean check:

class FunkyList(list):
    def __nonzero__(self):
        if self.__len__() == 0:
            return True
        else:
            return self.__len__()

    __bool__ = __nonzero__ # Python 3 uses __bool__ instead of __nonzero

But since both cases of the logic tree result in a bool of True, the above can be simplified to:

class FunkyList(list):
    def __nonzero__(self):
        return True

    __bool__ = __nonzero__ # Python 3 uses __bool__ instead of __nonzero

And we see it works and looks like a list:

>>> fl = FunkyList()
>>> fl
[]
>>> isinstance(fl, list)
True

And now bool() of the empty FunkyList returns True

>>> bool(fl)
True

And it does that without hacking the __len__ method.

>>> len(fl)
0

Regardless, I don't understand why you would want a list of len 0 to return True.

Thanks for such an interesting question, but I hope the matter is academic, and not practical. It's idiomatic of Python to do this check:

>>> if fl:
...     print True
... 
True

And anyone experienced in Python would expect that to return False if the list is empty, and the results of implementing this would probably make any user quite unhappy with you.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • Since many are curios of why I needed this here it goes. I am writing an INI file parser, in which I am using a subclass(say section) of list to represent a section in ini file. The section class behaves like a list in all ways but supports a few more methods . Another object(which represents a file itself as inifile) is holding a list of sections. the section in turn holds comments and key value pairs. While testing for the presence of a section in the inifile object I was always getting False and then I realised that it was because the section was empty. – Akilesh Jan 02 '14 at 06:35
  • The section is completely consumed by my module so I believe no one else would ever use it directly. I do believe there are other pythonic way of doing the same thing but I am just trying out. For now everything is working as I expected. – Akilesh Jan 02 '14 at 06:38
  • len(smthing)==0 adds unnecessary overhead to execution – volcano Jan 02 '14 at 13:16
  • @AaronHall, _not mylist_ is more than twice faster that _len(mylist)==0_. I think it is safe to assume that the former does not employ the latter implicitly. – volcano Jan 02 '14 at 14:02
  • yes, and it calls ``__len__`` but there's no way of getting around that. The biggest issue to me is the clarity of ``if foo:`` And if it always returns True, why are we using it in control flow? If it exists, it's always True, if it doesn't exist, it throws an error. To head off the matter, using exceptions for control flow is quite wrong, unless the conditional is quite exceptional, i.e. expected to be relatively rare. One might check if 'foo' in locals(), for existence, but that still says something's wrong with the program, to me. – Russia Must Remove Putin Jan 02 '14 at 14:03
  • I have two queries for you guys. First how do you evaluate the performance of code. Do you use some sort of tool to measure the time of execution. Second the choice of using if/else and try/except at what ratio of pass/fail does the performance of the latter get better. – Akilesh Jan 02 '14 at 17:06
  • 1
    @Akilesh check the `timeit` module – MestreLion Aug 06 '14 at 22:01
-5

i don't know whether it helpful for you but i tried this.... list_1= [["a","b"]] where ''list_1' is list name and '["a","b"]' is subset of list. if you execute following code

list_1 = [["a","b"]];
if "a" in list_1:
     print ("true");
else:
     print ("false");

will gives you "false" .....

if you execute this code

list_1 = [["a","b"]];
if "a" in list_1[0]:
     print ("true");
else:
     print ("false");

it will gives you "true"

by this way you can access sublist in list...

  • 1
    OP was about subclassing; this answer is for a question not asked (and to add insult to injury - C-style too) – volcano Jan 01 '14 at 07:57
  • 1
    ... and now you have to write [0] whenever you want to use the list. And len(list) is always 1. Are you serious about this Yogesh? – MestreLion Aug 06 '14 at 22:03