“is” operator not working as intended

后端 未结 3 1136
小鲜肉
小鲜肉 2021-01-15 12:02

Just have a look at this code:

import re

ti = \"abcd\"
tq = \"abcdef\"
check_abcd = re.compile(\'^abcd\')
print id(check_abcd.search(ti))
print id(check_abc         


        
相关标签:
3条回答
  • 2021-01-15 12:32

    Martjin has given you the correct answer, but for further clarification here is an annotated version of what's happening in your code:

    # this line creates returns a value from .search(), 
    # prints the id, then DISCARDS the value as you have not 
    # created a reference using a variable.
    print id(check_abcd.search(ti)) 
    
    # this line creates a new, distinct returned value from .search()
    # COINCIDENTALLY reusing the memory address and id of the last one.
    print id(check_abcd.search(tq))
    
    # Same, a NEW value having (by coincidence) the same id
    print check_abcd.search(ti)
    
    # Same again
    print check_abcd.search(tq)
    
    # Here, Python is creating two distinct return values.  
    # The first object cannot be released and the id reused
    # because both values must be held until the conditional statement has 
    # been completely evaluated.  Therefore, while the FIRST value will
    # probably reuse the same id, the second one will have a different id.
    if check_abcd.search(ti) is check_abcd.search(tq):
        print "Matching"
    else:
        print "not matching"
    
    0 讨论(0)
  • 2021-01-15 12:49

    You never assigned the return values, so after printing the id() value of the return value of check_abcd.search() calls, Python discards the return value object as there is nothing referencing it anymore. CPython object lifetimes are directly governed by the number of references to them; as soon as that reference count drops to 0 the object is removed from memory.

    Discarded memory locations can be re-used, so you'll like to see the same values crop up in id() calls. See the id() documentation:

    Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

    At no point in your code did you actually have one object, you have two separate objects with non-overlapping lifetimes.

    Assign return values if you want to make sure id() values are not reused:

    >>> import re
    >>> ti = "abcd"
    >>> tq = "abcdef"
    >>> check_abcd = re.compile('^abcd')
    >>> ti_search = check_abcd.search(ti)
    >>> tq_search = check_abcd.search(tq)
    >>> id(ti_search), id(tq_search)
    (4378421952, 4378422056)
    >>> ti_search, tq_search
    (<_sre.SRE_Match object at 0x104f96ac0>, <_sre.SRE_Match object at 0x104f96b28>)
    >>> ti_search is tq_search
    False
    

    By assigning the return values of check_abcd.search() (the regular expression MatchObjects) an additional reference is created and Python cannot reuse the memory location.

    0 讨论(0)
  • 2021-01-15 12:51

    WHen you do: print id(check_abcd.search(ti)) in a line and don't store the return value of search anywhere, its reference count goes to zero and it is destroyed. The call in the line bellow that creates another object, which happens to be in the same memory address (which is used by CPython as an object ID) - but it is not the same object.

    When you use the is operator, the previous object still has to exist in order for the comparison to occur, and its address will be different.

    Just put the results of the calls to check_abcd.search in a variable before printing their ID (and use different variables) and you will be able to see what is actually going on.

    Moreover: continuing in these lines can be instructive if you want to learn about the behavior of "is" and object IDs - but if you want to compare strings, and return values, just use the == operator, never is: subsequent function calls, even if returning the same value are not supposed to return the same object - the is comparison is only recommended when comparing with "None" (which is implemented as a singleton)

    0 讨论(0)
提交回复
热议问题