when to use == and when to use is
I know this question has been answered: http://stackoverflow.com/questions/6570371/when-to-use-and-when-to-use-is , but I still have doubts. Consider the following code: class A: def __init__(self, a): self._a = a #def __eq__(self, other): #return self._a != other._a obj_0 = A(0) obj_1 = A(1) obj_2 = A(2) obj = obj_1 if obj == obj_0: print(0) elif obj == obj_1: print(1) elif obj == obj_2: print(2) if obj is obj_0: print(0) elif obj is obj_1: print(1) elif obj is obj_2: print(2) Both if statements work, of course. Which is more efficient? My use-case scenario are matplotlib objects, the __eq__ operator might involve a bit of work. The if statement is a selector in a callback. I know that obj is one of obj_0, ..., or none of them. I do not care if obj_1 is equal to obj_2. George -- https://mail.python.org/mailman/listinfo/python-list
Re: when to use == and when to use is
On 3/10/14 2:09 PM, George Trojan wrote: I know this question has been answered: http://stackoverflow.com/questions/6570371/when-to-use-and-when-to-use-is , but I still have doubts. Consider the following code: class A: def __init__(self, a): self._a = a #def __eq__(self, other): #return self._a != other._a obj_0 = A(0) obj_1 = A(1) obj_2 = A(2) obj = obj_1 if obj == obj_0: print(0) elif obj == obj_1: print(1) elif obj == obj_2: print(2) if obj is obj_0: print(0) elif obj is obj_1: print(1) elif obj is obj_2: print(2) Both if statements work, of course. Which is more efficient? My use-case scenario are matplotlib objects, the __eq__ operator might involve a bit of work. The if statement is a selector in a callback. I know that obj is one of obj_0, ..., or none of them. I do not care if obj_1 is equal to obj_2. The last sentence seems telling to me: if you don't care if objects are equal, then don't use ==. Of course, a long change of if's to figure out which object you have seems odd to me... --Ned. George -- Ned Batchelder, http://nedbatchelder.com -- https://mail.python.org/mailman/listinfo/python-list
Re: when to use == and when to use is
George Trojan george.tro...@noaa.gov writes: Both if statements work, of course. Which is more efficient? I don't know. The answer is likely to be dependent on many details of the code and the data. But I do know that the different operators communicate different intents. And that should be a primary reason for choosing which operator to use: communicate your intent to the reader of the code. My use-case scenario are matplotlib objects, the __eq__ operator might involve a bit of work. Then IMO you should choose the operator which matches your intent, and stop worrying about “efficient” until you have measured exactly which part of the code is slow. It sounds like you are interested in value equality. So you should use ‘==’ for this purpose. -- \“A free press is one where it's okay to state the conclusion | `\ you're led to by the evidence.” —Bill Moyers | _o__) | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: when to use == and when to use is
I agree with Ben. In this particular case, it seems you really should be using == unless obj_0, obj_1, and obj_2 are sentinels. Skip -- https://mail.python.org/mailman/listinfo/python-list
when to use __new__, when to use __init__
I've dome some reading on the difference between __new__ and __init__, and never really groked it. I just followed the advice that you should almost always use __init__. I recently came across a task that required using __new__ and not __init__. I was a bit intimidated at first, but it was quick and easy. This simple programming exercise really cleared a lot of things up for me. Not to be immodest, but I think something like this ought to be the canonical example for explaining when/how to override __new__. The task? I want to make a class that behaves exactly like a tuple, except changing the constructor argument signature and adding some extra methods. An example should clarify what I needed. x = ParetoTuple(1, 2, 0) x[1] 2 len(x) 3 2 in x True -1 in x False x.dominates(ParetoTuple(1, 3, 0)) True x.equivalent(ParetoTuple(1, 2 + 1e-5, 0)) True etc. Since I want the constructor to take an (almost) arbitrary number of arguments, each of which will be elements of the resulting ParetoTuple, I need to override __new__. I don't need to overwrite __init__, because the tuple.__new__ will populate it's data when the arguments are properly formatted. Also, since the world of Pareto comparisons makes sense only with 2 or more goals, I want my specialized constructor to take at least 2 arguments in a natural way. Here is the code class ParetoTuple(tuple) : def __new__ (cls, obj1, obj2, *rest): return super(ParetoTuple, cls).__new__(cls, (obj1, obj2) + rest) # nothing special about the dominates, equivalents methods... # no __init__ needed I understand some people argue in favor of using a factory pattern for this sort of situation, but I disagree. I think the cognitive overhead of factories requires a more complicated task than re-signaturing the constructor method. At any rate, hope it helps others like it helped me. -- https://mail.python.org/mailman/listinfo/python-list
Re: when to use __new__, when to use __init__
On 10/14/2013 03:07 PM, Peter Cacioppi wrote: I've dome some reading on the difference between __new__ and __init__, and never really groked it. I just followed the advice that you should almost always use __init__. Object creation in Python is a two step process: - create the object (aka __new__, and make sure you return the new object! ;) - configure the object (aka __init__) If the object is immutable, everything has to be done in __new__. If the object is mutable, then you should split your code along the creation/configuration guidelines of __new__ and __init__, even though you could do it all in __new__. Why? To make subclassing easier. As an example, consider the new Enum[1] data type: my personal preference is to not specify the numbers, and to have docstrings on the Enum members. In order to achieve this I have to override __new__ as that is when the class structures are created, but I set the docstring in __init__: == class AutoEnum(Enum): Automatically numbers enum members starting from 1. Includes support for a custom docstring per member. __last_number__ = 0 def __new__(cls, *args): Ignores arguments (will be handled in __init__. value = cls.__last_number__ + 1 cls.__last_number__ = value obj = object.__new__(cls) obj._value_ = value return obj def __init__(self, *args): Can handle 0 or 1 argument; more requires a custom __init__. 0 = auto-number w/o docstring 1 = auto-number w/ docstring 2+ = needs custom __init__ (don't call this __init__) if len(args) == 1 and isinstance(args[0], (str, unicode)): self.__doc__ = args[0] elif args: raise TypeError('%s not dealt with -- need custom __init__' % (args,)) == Now, if I need some other Enum class with auto-numbering, but different arguments I can easily subclass AutoEnum: = class Rounds(AutoEnum): def __init__(self, x_length, y_length): self.x_length = x_length self.y_length = y_length SMALL_CICRLE = 100, 100 LARGE_ELLIPSE = 5000, 3000 = [1] enum34 is available on PyPI if you aren't able to move to Python3.4. -- ~Ethan~ -- https://mail.python.org/mailman/listinfo/python-list