What does x[x < 2] = 0 mean in Python?

前端 未结 5 778
南方客
南方客 2020-12-24 04:42

I came across some code with a line similar to

x[x<2]=0

Playing around with variations, I am still stuck on what this syntax does.

5条回答
  •  鱼传尺愫
    2020-12-24 04:52

    In general it could mean anything. It was already explained what it means if x is a list or numpy.ndarray but in general it only depends on how the comparison operators (<, >, ...) and also how the get/set-item ([...]-syntax) are implemented.

    x.__getitem__(x.__lt__(2))      # this is what x[x < 2] means!
    x.__setitem__(x.__lt__(2), 0)   # this is what x[x < 2] = 0 means!
    

    Because:

    • x < value is equivalent to x.__lt__(value)
    • x[value] is (roughly) equivalent to x.__getitem__(value)
    • x[value] = othervalue is (also roughly) equivalent to x.__setitem__(value, othervalue).

    This can be customized to do anything you want. Just as an example (mimics a bit numpys-boolean indexing):

    class Test:
        def __init__(self, value):
            self.value = value
    
        def __lt__(self, other):
            # You could do anything in here. For example create a new list indicating if that 
            # element is less than the other value
            res = [item < other for item in self.value]
            return self.__class__(res)
    
        def __repr__(self):
            return '{0} ({1})'.format(self.__class__.__name__, self.value)
    
        def __getitem__(self, item):
            # If you index with an instance of this class use "boolean-indexing"
            if isinstance(item, Test):
                res = self.__class__([i for i, index in zip(self.value, item) if index])
                return res
            # Something else was given just try to use it on the value
            return self.value[item]
    
        def __setitem__(self, item, value):
            if isinstance(item, Test):
                self.value = [i if not index else value for i, index in zip(self.value, item)]
            else:
                self.value[item] = value
    

    So now let's see what happens if you use it:

    >>> a = Test([1,2,3])
    >>> a
    Test ([1, 2, 3])
    >>> a < 2  # calls __lt__
    Test ([True, False, False])
    >>> a[Test([True, False, False])] # calls __getitem__
    Test ([1])
    >>> a[a < 2] # or short form
    Test ([1])
    
    >>> a[a < 2] = 0  # calls __setitem__
    >>> a
    Test ([0, 2, 3])
    

    Notice this is just one possibility. You are free to implement almost everything you want.

提交回复
热议问题