What is the difference with inv and invert?
>>> import operator
>>> operator.inv is operator.invert
False
>>> operator.__inv__ is operator.__invert__
False
I gather that __invert__ is the hook for the unary ops like ~1 or (1).__invert__().
But what is the other one __inv__ corresponding to? Or if it's same, why we have another name and a different function added for doing same thing?
Both represent the same operator. The long spelling was added in Python 2.0, and the short spelling was never removed.
operator.inv(obj)
operator.invert(obj)
operator.__inv__(obj)
operator.__invert__(obj)
Return the bitwise inverse of the number obj.
This is equivalent to ~obj.
New in version 2.0: The names invert() and __invert__().
Source: Python 2 operator documentation.
These are implemented as different objects because their representation reflects the name. Note that the corresponding dunder and regular names do share the same representation and object.
>>> operator.__inv__
<built-in function inv>
>>> operator.__invert__
<built-in function invert>
>>> operator.__inv__ is operator.inv
True
>>> operator.__invert__ is operator.invert
True
Historically, both names were equally viable - the Python 1 operator module used the inv/__inv__ name, whereas the Python 1 data model used the special method __invert__ name.
Related
I am getting a strange result in this boolean in python. I keep getting the wrong result.
string = '94070'
string[0:2] is '95' or string[0:2] is '94'
returns False, but when I hardcode in the value '94', it works
'94' is '95' or '94' is '94'
returns True. I've checked the data types and they are both of type 'str' so I'm not sure what is going on here.
Use == instead of is. In Python, the is operator does an object identity check. The == operator checks two objects (which may be different objects) to see whether they contain the same contents.
is is an identity test (is this the exact same object?), not equality test. While is works coincidentally, as an implementation detail for some things that aren't logically singletons, it shouldn't be used like this; use value equality testing with ==.
Your test of '94' is '94' can work due to a couple of related possibilities:
Python often coalesces constant literals in a function (sometimes only on a single line)
String literals are often interned by Python, so the same string literal expressed anywhere in the code references a common copy of that string
When you slice off bits of a string, interning isn't involved, so the identity test fails.
Use is to see if two arguments refer to the same object and == to see if they have the same value.
>>> a = 'this is some text.'
>>> b = 'this is some text.'
>>> a == b
True
>>> a is b
False
>>> a = 'this is some text.'
>>> b = a
>>> a == b
True
>>> a is b
True
So I am getting the following results:
() is () returns True (comparison between two objects)
id(()) is id(()) returns False. (comparison between the representations of object identities)
According to the python documentation:
The ‘is‘ operator compares the identity of two objects; the id() function returns an integer representing its identity.
Given case (1), object () has the same identity (memory address) as object (); but in case (2), the representations of their identities are not identical to each other.
Why is that?
The id(..) function returns an integer that represents the "identity" of an object so to speak. Although it is true that if two variables x and y refer to the same object, x is y succeed, and the result of id(x) is equal to id(y), that does not mean those integers themeselves are the same object.
You thus should use:
id(()) == id(())
# ^ == not is
In Python, even ints are objects, and although usually there is a cache such that small integers indeed refer to the same object, the following test will usually fail:
>>> 1234567890 is (1234567891-1)
False
>>> 1234567890 == (1234567891-1)
True
I came across a confusing problem when unit testing a module. The module is actually casting values and I want to compare this values.
There is a difference in comparison with == and is (partly, I'm beware of the difference)
>>> 0.0 is 0.0
True # as expected
>>> float(0.0) is 0.0
True # as expected
As expected till now, but here is my "problem":
>>> float(0) is 0.0
False
>>> float(0) is float(0)
False
Why? At least the last one is really confusing to me. The internal representation of float(0) and float(0.0) should be equal. Comparison with == is working as expected.
This has to do with how is works. It checks for references instead of value. It returns True if either argument is assigned to the same object.
In this case, they are different instances; float(0) and float(0) have the same value ==, but are distinct entities as far as Python is concerned. CPython implementation also caches integers as singleton objects in this range -> [x | x ∈ ℤ ∧ -5 ≤ x ≤ 256 ]:
>>> 0.0 is 0.0
True
>>> float(0) is float(0) # Not the same reference, unique instances.
False
In this example we can demonstrate the integer caching principle:
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
Now, if floats are passed to float(), the float literal is simply returned (short-circuited), as in the same reference is used, as there's no need to instantiate a new float from an existing float:
>>> 0.0 is 0.0
True
>>> float(0.0) is float(0.0)
True
This can be demonstrated further by using int() also:
>>> int(256.0) is int(256.0) # Same reference, cached.
True
>>> int(257.0) is int(257.0) # Different references are returned, not cached.
False
>>> 257 is 257 # Same reference.
True
>>> 257.0 is 257.0 # Same reference. As #Martijn Pieters pointed out.
True
However, the results of is are also dependant on the scope it is being executed in (beyond the span of this question/explanation), please refer to user: #Jim's fantastic explanation on code objects. Even python's doc includes a section on this behavior:
5.9 Comparisons
[7]
Due to automatic garbage-collection, free lists, and the dynamic nature of descriptors, you may notice seemingly unusual behaviour in certain uses of the is operator, like those involving comparisons between instance methods, or constants. Check their documentation for more info.
If a float object is supplied to float(), CPython* just returns it without making a new object.
This can be seen in PyNumber_Float (which is eventually called from float_new) where the object o passed in is checked with PyFloat_CheckExact; if True, it just increases its reference count and returns it:
if (PyFloat_CheckExact(o)) {
Py_INCREF(o);
return o;
}
As a result, the id of the object stays the same. So the expression
>>> float(0.0) is float(0.0)
reduces to:
>>> 0.0 is 0.0
But why does that equal True? Well, CPython has some small optimizations.
In this case, it uses the same object for the two occurrences of 0.0 in your command because they are part of the same code object (short disclaimer: they're on the same logical line); so the is test will succeed.
This can be further corroborated if you execute float(0.0) in separate lines (or, delimited by ;) and then check for identity:
a = float(0.0); b = float(0.0) # Python compiles these separately
a is b # False
On the other hand, if an int (or a str) is supplied, CPython will create a new float object from it and return that. For this, it uses PyFloat_FromDouble and PyFloat_FromString respectively.
The effect is that the returned objects differ in ids (which used to check identities with is):
# Python uses the same object representing 0 to the calls to float
# but float returns new float objects when supplied with ints
# Thereby, the result will be False
float(0) is float(0)
*Note: All previous mentioned behavior applies for the implementation of python in C i.e CPython. Other implementations might exhibit different behavior. In short, don't depend on it.
This question already has answers here:
What's the purpose of the + (pos) unary operator in Python?
(7 answers)
Closed 8 years ago.
I am writing a function computing like eval. When I come to float.__pos__ ,I really don't Know why there exists such a useless function. Because:
>>> float.__pos__(-1.0)
-1.0
>>> float.__pos__(1.0)
1.0
while float.__neg__ is totally different:
>>> float.__neg__(1.0)
-1.0
So what is the meaning of float.__pos__?
>>> help(float.__pos__)
Help on wrapper_descriptor:
__pos__(...)
x.__pos__() <==> +x
It's the "unary plus" operator, invoked when you do +x with x a float. It basically does nothing for floats, as you've discovered ;-) However, you could define a subclass that did something non-trivial with it. That's why it's there.
The __pos__ method defines the effect of the unary + operator for any object.
As Tim Peters mentions, it has no effect for floats.
See What's the purpose of the + (pos) unary operator in Python? for an example where it's used to do something.
Python has a unary negation operator to negate numbers, as you're probably well aware:
>>> x = 5
>>> print(-x)
-5
>>> x = -5
>>> print(-x)
5
Say you're making a list of numbers, though. It might be more consistent if you prefixed the positive ones with a +, so Python has a unary + operator, too:
>>> numbers = [-3, -2, -1, 0, +1, +2, +3]
When you use the unary + operator on a number, you're right that it doesn't do anything; it's there just for consistency.
Now when you consider that in Python you can override operators on types, of course you'd need a __neg__ to negate an instance of that type. Python just decided to be consistent by also having a __pos__ to…not negate an instance of that type. float, like all other types overriding these operators, follow this protocol, and float's implementation of __pos__ is just the identity function.
I've started learning Python (python 3.3) and I was trying out the is operator. I tried this:
>>> b = 'is it the space?'
>>> a = 'is it the space?'
>>> a is b
False
>>> c = 'isitthespace'
>>> d = 'isitthespace'
>>> c is d
True
>>> e = 'isitthespace?'
>>> f = 'isitthespace?'
>>> e is f
False
It seems like the space and the question mark make the is behave differently. What's going on?
EDIT: I know I should be using ==, I just wanted to know why is behaves like this.
Warning: this answer is about the implementation details of a specific python interpreter. comparing strings with is==bad idea.
Well, at least for cpython3.4/2.7.3, the answer is "no, it is not the whitespace". Not only the whitespace:
Two string literals will share memory if they are either alphanumeric or reside on the same block (file, function, class or single interpreter command)
An expression that evaluates to a string will result in an object that is identical to the one created using a string literal, if and only if it is created using constants and binary/unary operators, and the resulting string is shorter than 21 characters.
Single characters are unique.
Examples
Alphanumeric string literals always share memory:
>>> x='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
>>> y='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
>>> x is y
True
Non-alphanumeric string literals share memory if and only if they share the enclosing syntactic block:
(interpreter)
>>> x='`!##$%^&*() \][=-. >:"?<a'; y='`!##$%^&*() \][=-. >:"?<a';
>>> z='`!##$%^&*() \][=-. >:"?<a';
>>> x is y
True
>>> x is z
False
(file)
x='`!##$%^&*() \][=-. >:"?<a';
y='`!##$%^&*() \][=-. >:"?<a';
z=(lambda : '`!##$%^&*() \][=-. >:"?<a')()
print(x is y)
print(x is z)
Output: True and False
For simple binary operations, the compiler is doing very simple constant propagation (see peephole.c), but with strings it does so only if the resulting string is shorter than 21 charcters. If this is the case, the rules mentioned earlier are in force:
>>> 'a'*10+'a'*10 is 'a'*20
True
>>> 'a'*21 is 'a'*21
False
>>> 'aaaaaaaaaaaaaaaaaaaaa' is 'aaaaaaaa' + 'aaaaaaaaaaaaa'
False
>>> t=2; 'a'*t is 'aa'
False
>>> 'a'.__add__('a') is 'aa'
False
>>> x='a' ; x+='a'; x is 'aa'
False
Single characters always share memory, of course:
>>> chr(0x20) is ' '
True
To expand on Ignacio’s answer a bit: The is operator is the identity operator. It is used to compare object identity. If you construct two objects with the same contents, then it is usually not the case that the object identity yields true. It works for some small strings because CPython, the reference implementation of Python, stores the contents separately, making all those objects reference to the same string content. So the is operator returns true for those.
This however is an implementation detail of CPython and is generally neither guaranteed for CPython nor any other implementation. So using this fact is a bad idea as it can break any other day.
To compare strings, you use the == operator which compares the equality of objects. Two string objects are considered equal when they contain the same characters. So this is the correct operator to use when comparing strings, and is should be generally avoided if you do not explicitely want object identity (example: a is False).
If you are really interested in the details, you can find the implementation of CPython’s strings here. But again: This is implementation detail, so you should never require this to work.
The is operator relies on the id function, which is guaranteed to be unique among simultaneously existing objects. Specifically, id returns the object's memory address. It seems that CPython has consistent memory addresses for strings containing only characters a-z and A-Z.
However, this seems to only be the case when the string has been assigned to a variable:
Here, the id of "foo" and the id of a are the same. a has been set to "foo" prior to checking the id.
>>> a = "foo"
>>> id(a)
4322269384
>>> id("foo")
4322269384
However, the id of "bar" and the id of a are different when checking the id of "bar" prior to setting a equal to "bar".
>>> id("bar")
4322269224
>>> a = "bar"
>>> id(a)
4322268984
Checking the id of "bar" again after setting a equal to "bar" returns the same id.
>>> id("bar")
4322268984
So it seems that cPython keeps consistent memory addresses for strings containing only a-zA-Z when those strings are assigned to a variable. It's also entirely possible that this is version dependent: I'm running python 2.7.3 on a macbook. Others might get entirely different results.
In fact your code amounts to comparing objects id (i.e. their physical address). So instead of your is comparison:
>>> b = 'is it the space?'
>>> a = 'is it the space?'
>>> a is b
False
You can do:
>>> id(a) == id(b)
False
But, note that if a and b were directly in the comparison it would work.
>>> id('is it the space?') == id('is it the space?')
True
In fact, in an expression there's sharing between the same static strings. But, at the program scale there's only sharing for word-like strings (so neither spaces nor punctuations).
You should not rely on this behavior as it's not documented anywhere and is a detail of implementation.
Two or more identical strings of consecutive alphanumeric (only) characters are stored in one structure, thus they share their memory reference. There are posts about this phenomenon all over the internet since the 1990's. It has evidently always been that way. I have never seen a reasonable guess as to why that's the case. I only know that it is. Furthermore, if you split and re-join alphanumeric strings to remove spaces between words, the resulting identical alphanumeric strings do NOT share a reference, which I find odd. See below:
Add any non-alphanumeric value identically to both strings, and they instantly become copies, but not shared references.
a ="abbacca"; b = "abbacca"; a is b => True
a ="abbacca "; b = "abbacca "; a is b => False
a ="abbacca?"; b = "abbacca?"; a is b => False
~Dr. C.
'is' operator compare the actual object.
c is d should also be false. My guess is that python make some optimization and in that case, it is the same object.