Prev: 2to3 on Mac - unknown encoding: mbcs
Next: safely returning objects from a Process to the parent through aQueue()
From: Terry Reedy on 7 Nov 2009 15:31 Steven D'Aprano wrote: > On Fri, 06 Nov 2009 16:51:18 +0100, Marco Mariani wrote: > >> Using "x is y" with integers >> makes no sense and has no guaranteed behaviour AFAIK > > Of course it makes sense. `x is y` means *exactly the same thing* for > ints as it does with any other object: it tests for object identity. > That's all it does, and it does it perfectly. > > Python makes no promise whether x = 3; y = 3 will use the same object for > both x and y or not. That's an implementation detail. That's not a > problem with `is`, it is a problem with developers who make unjustified > assumptions. Which is to say, it normally makes no sense to write 'm is n' for m, n ints. The *exception* is when one is exploring implementation details, either to discover them or to test that they are as intended. So, last I looked, the test suite for ints makes such tests. If the implementation changes, the test should change also. The problem comes when newbies use 'is' without realizing that they are doing black-box exploration of otherwise irrelevant internals. (White-box exploration would be reading the code, which makes it plain what is going on ;-). Terry Jan Reedy
From: sturlamolden on 7 Nov 2009 17:22 On 6 Nov, 14:35, "Alf P. Steinbach" <al...(a)start.no> wrote: > As I understand it, 'is' will always work and will always be efficient (it just > checks the variable's type), while '==' can depend on the implementation of > equality checking for the other operand's class. '==' checks for logical equality. 'is' checks for object identity. None is a singleton of type NoneType. Since None evaluates to True only when compared against itself, it is safe to use both operators.
From: sturlamolden on 7 Nov 2009 17:27 On 6 Nov, 18:28, "Alf P. Steinbach" <al...(a)start.no> wrote: > Dynamic allocation isn't hare-brained, but doing it for every stored integer > value outside a very small range is, because dynamic allocation is (relatively > speaking, in the context of integer operations) very costly even with a > (relatively speaking, in the context of general dynamic allocation) very > efficient small-objects allocator - here talking order(s) of magnitude. When it matters, we use NumPy and/or Cython.
From: sturlamolden on 7 Nov 2009 17:54 On 6 Nov, 17:54, "Alf P. Steinbach" <al...(a)start.no> wrote: > But wow. That's pretty hare-brained: dynamic allocation for every stored value > outside the cache range, needless extra indirection for every operation. First, integers are not used the same way in Python as they are in C+ +. E.g. you typically don't iterate over them in a for loop, but rather iterate on the container itself. Second, if you need an array of integers or floats, that is usually not done with a list: you would use numpy.ndarray or array.array, and values are stored compactly. A Python list is a list, it is not an array. If you were to put integers in dynamic data structures in other languages (Java, C++), you would use dynamic allocation as well. Yes a list is implemented as an array of pointers, amortized to O(1) for appends, but that is an implementation detail. Python is not the only language that works like this. There are also MATLAB and Lisp. I know you have a strong background in C++, but when you are using Python you must unlearn that way of thinking. Finally: if none of these helps, we can always resort to Cython. In 99% of cases where integers are bottlenecks in Python, it is indicative of bad style. We very often see this from people coming form C++ and Java background, and subsequent claims that "Python is slow". Python is not an untyped Java. If you use it as such, it will hurt. Languages like Python, Perl, Common Lisp, and MATLAB require a different mindset from the programmer.
From: Steven D'Aprano on 7 Nov 2009 18:09
On Sat, 07 Nov 2009 14:22:28 -0800, sturlamolden wrote: > On 6 Nov, 14:35, "Alf P. Steinbach" <al...(a)start.no> wrote: > >> As I understand it, 'is' will always work and will always be efficient >> (it just checks the variable's type), while '==' can depend on the >> implementation of equality checking for the other operand's class. > > '==' checks for logical equality. 'is' checks for object identity. So far so good, although technically == merely calls __eq__, which can be over-ridden to do (nearly) anything you like: >>> class Funny(object): .... def __eq__(self, other): .... return self.payload + other .... >>> f = Funny() >>> f.payload = 5 >>> f == 10 15 > None is a singleton of type NoneType. Since None evaluates to True only > when compared against itself, That's wrong. None never evaluates to True, it always evaluates as None, in the same way that 42 evaluates as 42 and [1,2,3] evaluates as [1,2,3]. Python literals evaluate as themselves, always. Perhaps you mean that *comparisons* of None evaluate to True only if both operands are None. That's incorrect too: >>> None > None False You have to specify the comparison. It would be a pretty strange language if both None==None and None!=None returned True. > it is safe to use both operators. Only if you want unexpected results if somebody passes the wrong sort of object to your code. >>> class NoneProxy: .... def __eq__(self, other): .... if other is None: return True .... return False .... >>> o = NoneProxy() >>> o is None False >>> o == None True You should use == *only* if you want to test for objects which are equal to None, *whatever that object may be*, and is if you want to test for None itself. -- Steven |