[Python-ideas] Re: Add __eq__ to colletions.abc.Sequence ?
Are all objects in Python equality-comparable? I know that you can delete __hash__ to make an object unhashable (e.g., dicts). If so, this is a great addition. On Saturday, July 4, 2020 at 5:26:45 PM UTC-4, Joao S. O. Bueno wrote: > > > > On Sat, 4 Jul 2020 at 16:51, Serhiy Storchaka > wrote: > >> 30.06.20 18:58, Joao S. O. Bueno пише: >> > I ended up writting an __eq__ - and in the process I found it is not >> > _that_ straightforward due >> > to having to check subclasses types when comparing. >> > (given Base sequence A, child class B(A), class C(A) and class B1(B) - >> > Instances of B and B1 can be >> > equal, but instances of B and C should always be different) - or in >> > Python, inside __eq__ : >> > if not issubclass(type(other), type(self)) and not >> > issubclass(type(self), type(other)): >> > return False >> >> It would be more correct to return NotImplemented. >> >> Also, it is enough to test isinstance(other, type(self)) because >> other.__eq__(self) be called first if the type of other is a subclass of >> the type of self. >> > > Ah - yes. Half the logic is already on the __eq__ semantics - thanks. > Well, I am updating that on my code right now. > > Anyway I am not seeing anyone opposing this going into col...abc.Sequence > - > Maybe it is ok for a BPO? > > (yes, there is this consideration I had, and also Guido, > that it would create new behavior in classes that already exist, but I saw > no way that could break code not specially crafted to break with this > change.) > > > ___ >> Python-ideas mailing list -- python...@python.org >> To unsubscribe send an email to python-id...@python.org >> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >> Message archived at >> https://mail.python.org/archives/list/python-ideas@python.org/message/K2P4ZWF6FIRPCRKUH7IHZHMC7E3HVJER/ >> Code of Conduct: http://python.org/psf/codeofconduct/ >> >___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/FXJWTXQWTW7C32JBEBOIYLYOXVDLTQ2P/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020, 10:25 PM Steven D'Aprano wrote: > > The standard library *does* seem to have taken pains to avoid > "finite nans." > > I don't know what you mean by "finite nans". By definition, any NAN is not > considered finite. > The scare quotes because I know that's not a real thing. Maybe "genetically finite" ... I.e. do some operations on regular finite values that wind up with NaN. I know, I know... That's not really right either, since finite values can overflow to infinities on their own. Do you mean, the stdlib has taken pains to avoid returning NANs ex novo, > i.e. from purely finite arguments? Then I agree. > Yes. That's it. :-) > min() and max() are notable, and unfortunate, exceptions in that their > treatment of NANs depends on the order of argument. I would call that a bug > except that the statistics module (which I wrote) has the same flaw, and > I've argued in the past that this is not a bug :-) > Personal growth is healthy! That's not the trig functions' fault, it's the fact that we cannot > exactly represent pi/2 exactly. I'm not sure what you mean by pruning > them, it is pretty much standard that tan(pi/2) doesn't fail: > Of course. math.pi is a number that isn't really pi, as any finite representation must be. tan() is doing the right thing. I just meant that if math.cot() were added to the standard library, I could pass an exact zero as argument. None of the trig or hyperbolic functions that are undefined at ZERO are included. But yes, math.log(0) is another one where a NaN is avoided in favor of an exception. A few different log bases, but same story for all. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ZVBGV7UDCFC4OEFE5UFV7ZNUFK223ZIC/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Mon, Jul 6, 2020 at 12:36 PM Steven D'Aprano wrote: > Four years ago, there was strong opposition to giving the bounds default > values. I think the consensus at the time was that it is okay to > explicitly provide "unbounded" arguments (whether you spell them as > infinities, NANs, or None) but you should have to explicitly do so: > > clamp(x) > > just reads poorly. Yes, but it's also useless (clamping without ANY bounds?). In terms of reading poorly, this is far worse: clamp(x, 10) Does that ensure that it's no *greater* than 10 or no *less* than 10? Since the args would be min before max, I would expect that this has a lower bound and no upper bound, but there'll be people equally confident that it should behave like range() and have an upper bound with no lower bound (which would probably be more useful in a lot of situations anyway). So I also agree that the bounds should be given explicitly. ChrisA ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/J5ZPUKV7IMQDJVHF6HTNQNNA6AJZNDMF/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Mon, Jul 06, 2020 at 03:21:04AM +0100, Henk-Jaap Wagenaar wrote: > I do not agree clamp should be restricted to numeric values. I would expect > clamp to be agnostic to the specifics of floats/numbers and like sort > expect it to work for any values as long as they compare (using a dunder). It is possible to write clamp so that it relies only on two things: - the bounds must support equality and less than; - the value must support less than. That is pretty much as general as it gets. I think that it is okay to document clamp as *intended* for numbers but allow it to be used for non-numbers, similar to the builtin sum(). (Although sum needs to be tricked into supporting strings.) Four years ago, there was strong opposition to giving the bounds default values. I think the consensus at the time was that it is okay to explicitly provide "unbounded" arguments (whether you spell them as infinities, NANs, or None) but you should have to explicitly do so: clamp(x) just reads poorly. I concur with that argument -- or at least, I don't disagree strongly enough to argue against it. This is why the implementation I posted earlier accepts None as bounds, but doesn't give them defaults. -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/CKL734WLAZ26OWPJHCTCM2QIDCLFH622/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 05, 2020 at 09:42:07PM -0400, David Mertz wrote: > The standard library *does* seem to have taken pains to avoid "finite > nans." I don't know what you mean by "finite nans". By definition, any NAN is not considered finite. py> math.isfinite(math.nan) False Do you mean, the stdlib has taken pains to avoid returning NANs ex novo, i.e. from purely finite arguments? Then I agree. > It kinda weakens your case about worrying about doing clamp() right > in the face of NaNs :-). Are you suggesting that we should do clamp() wrong instead? *wink* What I intended is that the stdlib tends to raise rather than return a NAN from some calculation not already including NANs or INFs. But if you pass NANs into the calculation, then the stdlib honours them. py> math.atan(math.nan) nan So if you pass a NAN to clamp(), it should do the right thing, which may be returning a NAN: clamp(NAN, -1, 1) # Should certainly return a NAN. or may not: clamp(NAN, 1, 1) # Should certainly return 1. Only the behaviour when one or the other of the bounds are NANs is controversial. I acknowledge that there are two good behaviours, and it is reasonable for people to want one or the other. I have argued why one is better and less inconvenient than the other, but I won't rehash that argument here. min() and max() are notable, and unfortunate, exceptions in that their treatment of NANs depends on the order of argument. I would call that a bug except that the statistics module (which I wrote) has the same flaw, and I've argued in the past that this is not a bug :-) But in both cases, statistics and min/max, it is clear that the order-dependent behaviour satisfies nobody and is undesirable. > It also looks like the trig functions are pruned to those that don't have > undefined values for numbers I can type in. I can *type* > `math.tan(math.pi/2)`, of course. But math.pi is a little bit smaller than > the actual pi, so I just get a big number for an answer. That's not the trig functions' fault, it's the fact that we cannot exactly represent pi/2 exactly. I'm not sure what you mean by pruning them, it is pretty much standard that tan(pi/2) doesn't fail: https://stackoverflow.com/questions/20287765/math-tan-near-pi-2-wrong-in-net-right-in-java and that comes out of the floating point representation, not tan. > But I cannot try the hypothetical: > > >>> math.cot(0) > nan No, but you could try this instead: py> math.log(0.0) Traceback (most recent call last): File "", line 1, in ValueError: math domain error -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/N7OCELBGCNAO5LUKBBTRKR35MB4AGSOJ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
I do not agree clamp should be restricted to numeric values. I would expect clamp to be agnostic to the specifics of floats/numbers and like sort expect it to work for any values as long as they compare (using a dunder). I think having something like min=-math.inf is hence right out in my mind. If I got this right, the implementation could be as simple as: def clamp(value, *, min=None, max=None): if min is not None and value < min: return min if max is not None and max < value: return max return value I think the crucial question here is: does the order of the ifs matter and is that an issue. The only time (barring side effects, values changing in between calls et cetera) it would make a difference if max < value < min. Assuming transitivity (can anybody come up with an example of a non-transitive order where clamping makes sense?) this means max < min and so you can work around this by disallowing it: def clamp_safe(value, * min=None, max=None): if max < min: raise SomeException("Something about min < max") return clamp(value, min=min, max=max) What I like about both of these is that they only use "<", just like sort. Going back to nans, I think that would mean: clamp(nan, min, max) = nan clamp(value, nan, max) = clamp(value, None, max) = max(value, max) clamp(value, min, nan) = clamp(value, min, None) = min(value, min) On Mon, 6 Jul 2020 at 02:55, Christopher Barker wrote: > > and we can use +inf and -inf for unlimited bounds as well. Yes, they are a > bit of a pain to write in Python, but we could do: > > def clamp(value, min=-math.inf, max=math.inf): > ... > > yes, that would make them optional, rather than required, and therefore > provide a slight asymmetry between specifying min only or max only, but > still be handy. to make it more consistent, but maybe more annoying in the > common case, we could make them keyword only. > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3AXOG34FEMLAWIQQTBH3CZ5J4JL4GJE7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 10:04 PM Christopher Barker wrote: > Since you brought that up -- I recall a lot of debate about whether NaN's > should be considered missing values or "poisoning" in the statistics module > -- there are arguments for both, and neither was clear or obvious. So using > NaN to mean "not specified" in this context would not be obvious to > everyone, and when we have the perfectly good None instead, why do it? > Well, yes... I wrote a lot of that debate :-) I even sort of re-discovered quick select on my own... then eventually figured out that a bunch of people had benchmarked a better implementation to potentially use in statistics.median() a year before I tried. Python sorted() is really fast! But it's still the WRONG way to do this, or at least there should be a switch to allow nan-poisoning and/or nan-stripping. Btw, definitely +1 on math.clamp(value, *, lower=None, upper=None) . >> > > what about: > > math.clamp(value, *, lower=-math.inf, upper=math.inf) . > Oh sure. That's fine. But the implementation would still need to check for None and convert it to the infinities. Ordinary users just simply ARE going to try: math.clamp(x, lower=None, upper=99) And expect that to mean "I don't care about lower bound." -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/JMNU4L42AAGKFGF6CSUW3CWY574QUFIM/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 6:51 PM David Mertz wrote: > > will always return x for every finite and infinite value, so it must >> return x for NANs too. >> > > I strongly agree with Steven here. Also about order-dependence in results > of min() and max() being disturbing and contrary to IEEE-754. > > ... so, umm... Steven... statistics.median()?! > Since you brought that up -- I recall a lot of debate about whether NaN's should be considered missing values or "poisoning" in the statistics module -- there are arguments for both, and neither was clear or obvious. So using NaN to mean "not specified" in this context would not be obvious to everyone, and when we have the perfectly good None instead, why do it? Btw, definitely +1 on math.clamp(value, *, lower=None, upper=None) . > what about: math.clamp(value, *, lower=-math.inf, upper=math.inf) . Also it seems we can have "NaN poisoning" behaviour without explicitly checking for it. The real key is not that it's a NaN, but that it doesn't compare as True to anything. Someone smarter than me could probably make this cleaner, but this works: In [112]: def min(x, y): ...: if x < y: ...: return x ...: elif y <= x: ...: return y ...: else: ...: return x if not (x < math.inf) else y Note that I did that ugly ternary expression at the end in hopes that it would work with non-float NaN-like objects, but no luck there, at least not with Decimal: In [113]: min(1, Decimal('NaN')) --- InvalidOperation Traceback (most recent call last) in > 1 min(1, Decimal('NaN')) in min(x, y) 1 def min(x, y): > 2 if x < y: 3 return x 4 elif y <= x: 5 return y InvalidOperation: [ It seems that Decimal Nan does not behave like FP NaNs :-( -1 on built-in. -0 on any other function signature. Actually, I'm fine with math.clip() as well, but clamp seems more popular. One thing about putting it in the math module is that we could then make assumptions about the float type. And we'd have to write it in C, so it would be fast, even if there is some ugly NaN-checking behavior and the like. -CHB -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/V3XVFUNWATUWEJUS64JNLEJBPJ6HWGJH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 6:01 PM Greg Ewing wrote: > On 6/07/20 3:55 am, Steven D'Aprano wrote: > > With that interpretation, a NAN passed as the lower or upper bounds can > > be seen as another way of saying "no lower bounds" (i.e. negative > > infinity) or "no upper bounds" (i.e. positive infinity), not "some > > unknown bounds". > > Python already has a value for representing missing or unspecified > data, i.e. None. So we don't need to use NaN for that, and can > instead reserve it to mean "no correct answer". > +1 and we can use +inf and -inf for unlimited bounds as well. Yes, they are a bit of a pain to write in Python, but we could do: def clamp(value, min=-math.inf, max=math.inf): ... yes, that would make them optional, rather than required, and therefore provide a slight asymmetry between specifying min only or max only, but still be handy. to make it more consistent, but maybe more annoying in the common case, we could make them keyword only. > I agree with you that `clamp(lower=x, value=NAN, upper= x)` should > > return x. > > I don't think I agree with that, because it relies on assuming that > the lower and upper bounds can meaningfully be compared for exact > equality, which may not be true depending on the circumstances. > and then we'd need to check if they were equal as well. > > Treat a NAN bounds as *missing data*, which effectively means "there is > > no limit", i.e. as if you had passed the infinity of the appropriate > > sign for the bounds. > and really how often would one end up with NaN as a bound anyway? Often they will be hard-coded. I"m having a really hard time imagining when you'd end up with NaN for a bound that was NOT an error! It would be far more likely for the value you want clamped to be NaN -- and then it sure as heck should return NaN. As for the behavior of min() and max() when provided a NaN (and much of Python's handling of FP special values) -- I think that's a practicality-beats-purity issue. I have a really hard time thinking that anyone thinks that: In [81]: min(1, math.nan) Out[81]: 1 In [82]: min(math.nan, 1) Out[82]: nan is ideal behavior! while I was writing this: On Sun, Jul 5, 2020 at 6:38 PM Steven D'Aprano wrote: > ... on this point at least the IEEE-754 standard is firm: if a > function will return the same result for every non-NAN argument, then it > must return the same result for NAN arguments too. > > clamp(value, x, x) > > will always return x for every finite and infinite value, so it must > return x for NANs too. Except that Python (maybe except for the math module) does not conform to IEEE-754 in many other places. So we do have a practicality beats purity choice here. -CHB -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/Z5FBFJKBOJNDWOCGD7INMKPRN3YAS36V/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 9:38 PM Steven D'Aprano wrote: > > >I agree with you that `clamp(lower=x, value=NAN, upper= x)` should > > >return x. > > Sorry Greg, on this point at least the IEEE-754 standard is firm: if a > function will return the same result for every non-NAN argument, then it > must return the same result for NAN arguments too. > > clamp(value, x, x) > > will always return x for every finite and infinite value, so it must > return x for NANs too. > I strongly agree with Steven here. Also about order-dependence in results of min() and max() being disturbing and contrary to IEEE-754. ... so, umm... Steven... statistics.median()?! Btw, definitely +1 on math.clamp(value, *, lower=None, upper=None) . -1 on built-in. -0 on any other function signature. Actually, I'm fine with math.clip() as well, but clamp seems more popular. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7X64MLI6G4Q5ZSIZNBRCU3HAYWWWYOI3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 8:57 PM Steven D'Aprano wrote: > On Sun, Jul 05, 2020 at 12:15:27PM -0400, David Mertz wrote: > > This is a digression, but does anyone have a nice example IN PYTHON of > > arriving at a NaN without going through infinity. I think Julia is right > > and Python is wrong about '0/0', but as things are, that's not an > example. > > I wouldn't expect one in Python, I think there is an unofficial policy > of ensuring that Python builtins and the math library will not return > NANs unless passed a NAN, or at least an INF, rather they will raise. > > > > >>> 1e1000-1e1000 > > > nan > is just a funny way of writing INF - INF :-) > The standard library *does* seem to have taken pains to avoid "finite nans." It kinda weakens your case about worrying about doing clamp() right in the face of NaNs :-). I recognize there are funny ways of writing infinity. But since Python really doesn't quite follow IEEE-754 on 0/0, or math.fmod(x, 0.), or a few other places it might arise in "natural" operations (i.e. it's easy not to notice that your 'y' has become zero. It also looks like the trig functions are pruned to those that don't have undefined values for numbers I can type in. I can *type* `math.tan(math.pi/2)`, of course. But math.pi is a little bit smaller than the actual pi, so I just get a big number for an answer. But I cannot try the hypothetical: >>> math.cot(0) nan For what we actually have: >>> math.tan(math.pi/2) 1.633123935319537e+16 One ULP more: >> math.tan(np.nextafter(math.pi/2, np.inf)) -6218431163823738.0 -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/P742DYSQAMWKAAKNPASMDSEXH6AGEXKO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Mon, Jul 06, 2020 at 12:59:28PM +1200, Greg Ewing wrote: > >I agree with you that `clamp(lower=x, value=NAN, upper= x)` should > >return x. > > I don't think I agree with that Sorry Greg, on this point at least the IEEE-754 standard is firm: if a function will return the same result for every non-NAN argument, then it must return the same result for NAN arguments too. clamp(value, x, x) will always return x for every finite and infinite value, so it must return x for NANs too. Quoting one of the standard committee members: NaN must not be confused with “Undefined.” On the contrary, IEEE 754 defines NaN perfectly well even though most language standards ignore and many compilers deviate from that definition. The deviations usually afflict relational expressions, discussed below. Arithmetic operations upon NaNs other than SNaNs (see below) never signal INVALID, and always produce NaN unless replacing every NaN operand by any finite or infinite real values would produce the same finite or infinite floating-point result independent of the replacements. https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF See page 7. This is why 1.0**NAN returns 1.0, and why math.hypot(INF, NAN) returns INF. > because it relies on assuming that > the lower and upper bounds can meaningfully be compared for exact > equality, which may not be true depending on the circumstances. I don't understand that objection. Can you give a concrete example? > >Treat a NAN bounds as *missing data*, which effectively means "there is > >no limit", i.e. as if you had passed the infinity of the appropriate > >sign for the bounds. > > If one of the bounds is missing, you don't need clamp(), you > can use min() or max(). Only if you know it is missing. If the bounds come from some other calculation or from the user, how do you know they are missing? if lower is upper is None: pass elif lower is None: value = min(value, upper) elif upper is None: value = max(value, lower) else: value = clamp(value, lower, upper) We don't have three slice functions to cover the cases where one or the other bounds is missing: slice(start, stop) slice_end_at(stop) slice_start_at(start) we just have a single function that takes a missing value. -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/R3IBF2EBARO6BJ7KKIWRJ57VWKLC7DN7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: giving set.add a return value
Sorry, this got lost in the shuffle without being sent, and the conversation seems to have died down. but since I wrote it ... On Sat, Jul 4, 2020 at 8:25 AM Stephen J. Turnbull < turnbull.stephen...@u.tsukuba.ac.jp> wrote: > Christopher Barker writes: > > > I am really confused here -- I'm suggesting that is should NOT be > possible > > to tell the difference. > > But it is possible to tell the difference, so that suggestion is moot. I meant in the context of putting things in, or testing whether they are in, sets. Not in any other context. There are languages where there is no numeric tower, just numbers, and > [0][0], [0][0.0], and [0][0+0j] all just work. Python isn't one of > them. Fewer places you can tell in Python 3 than in Python 2, I > believe, but several remain. Sure, but putting them in sets, or using them as a key in a dict is not one of them. set.intern does yield the same result regardless of what's passed in: > whichever is in the set. That's *why* I can call it "intern".[1] Fair enough. You can of course propose any functionality you want. I’m suggesting that my understanding of what you are proposing doesn’t match well with the rest of how sets work. But to see if I understand correctly, you couldn’t quite use a set to intern objects: once 2.0 was in there you could not put 2 in as well. You could know that 2.0 was already in there when you tried to add 2, but it would still never be added. It seems if you really want to intern objects, you’d need something kind of like, but not quite, a set(). Note: this all is only an issue for object that are of a different type, but can compare equal and have the same hash - maybe the numeric types are the only ones in the stdlib for which this is the case. Nevertheless, they are commonly used :-) Nope: turns out NamedTuples and Tuple are the "same" as far as sets are concerned as well. In [66]: s = {p} In [67]: s Out[67]: {Point(x=2, y=3)} In [68]: s.add((2,3)) In [69]: s Out[69]: {Point(x=2, y=3)} In [70]: s = {(2,3)} In [71]: s.add(p) In [72]: s Out[72]: {(2, 3)} So if you want something that treats different types with the same value as different, you really will need a different storage mechanism than a set. -CHB ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/JKK6J7CGWLLSOQATFD5JRL6VAS3YQGGI/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 6/07/20 3:55 am, Steven D'Aprano wrote: With that interpretation, a NAN passed as the lower or upper bounds can be seen as another way of saying "no lower bounds" (i.e. negative infinity) or "no upper bounds" (i.e. positive infinity), not "some unknown bounds". Python already has a value for representing missing or unspecified data, i.e. None. So we don't need to use NaN for that, and can instead reserve it to mean "no correct answer". I agree with you that `clamp(lower=x, value=NAN, upper= x)` should return x. I don't think I agree with that, because it relies on assuming that the lower and upper bounds can meaningfully be compared for exact equality, which may not be true depending on the circumstances. Treat a NAN bounds as *missing data*, which effectively means "there is no limit", i.e. as if you had passed the infinity of the appropriate sign for the bounds. If one of the bounds is missing, you don't need clamp(), you can use min() or max(). -- Greg ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/WD4RO57XMIKUDYWAXCRPE3MSJ2RZEBRU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 05, 2020 at 12:15:27PM -0400, David Mertz wrote: > This is a digression, but does anyone have a nice example IN PYTHON of > arriving at a NaN without going through infinity. I think Julia is right > and Python is wrong about '0/0', but as things are, that's not an example. I wouldn't expect one in Python, I think there is an unofficial policy of ensuring that Python builtins and the math library will not return NANs unless passed a NAN, or at least an INF, rather they will raise. Chris' example: > > >>> 1e1000-1e1000 > > nan is just a funny way of writing INF - INF :-) -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/DT4GE4UAPSAPPV3DSFF7SHEP3QR6BZGD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 05, 2020 at 11:58:58AM -0700, Bruce Leban wrote: > > People who want NAN poisoning can opt-in by doing a check for NANs > > themselves, either in a wrapper function, or by testing the bounds > > *once* ahead of time and then just calling the stdlib `clamp` once they > > know they aren't NANs. > > > Imagine making the same statement about exceptions: > > Exceptions being raised should be opt-in. > > > That sounds crazy but it's not. Before exceptions were commonplace, there > were three possibilities when unreasonable operations were performed: But using a NAN is not an unreasonable operation. There is a perfectly sensible interpretaion available for using NANs as bounds, and it is one which is supported by the IEEE-754 recommended treatment of minimum and maximum: missing values. That same behaviour falls out naturally from a very simple, non- contrived and efficient implementation of clamp that relies only on the value supporting less than. (The bounds also have to support equality.) It doesn't even have to be numeric! So long as the value supports less than, you can clamp it. Whether that is meaningful or not depends on the value, but the feature is there for those who can make use of it. Duck-typing for the win! >- return some arbitrary or random value (not a NaN because they hadn't >been invented); IEEE-754 goes back to the 1980s, before exceptions were commonplace. So returning a NAN was certainly an option. On the Apple Mac, converting a string to a float would return a NAN if it was a non-numeric value like "abc". So did operations like arcsin(2). >- and also set an "error flag" that could be checked by the caller to >determine if something had gone wrong (but frequently was not); >- terminate the program. > > Things are much better now. Few argue that it was better before. There are many people who consider exceptions to be a terrible mistake, including the creators of Go. So your analogy is not as strong as you think. > Think of > NaN as the value equivalent of an exception. NaN poisoning is the > equivalent of the fact that any function that doesn't catch an exception > passes it through. Right. That's an excellent analogy. If exceptions were uncatchable, they would always be fatal and they would be just like the bad old days where any error would always terminate the program. But they aren't uncatchable, and there are situations where NANs don't represent a fatal error that can only propagate through your calculation poisoning the results. Here are some examples: py> 1 < NAN False py> min(max(1, NAN), NAN) 1 py> 1**NAN 1.0 The first two are especially relevant for clamp. > I don't usually write code that *uses *NaNs directly. If > I want a distinguished non-numeric value, I use None or some other > sentinel. If a NaN is produced by my code it indicates a bug. NaN poisoning > increases the chance that a NaN generated somewhere won't be hidden by > later code that manipulates that value. Why would I want to suppress that? Then don't. I'm happy for you to test for it. Write a wrapper function that checks the bounds, and you are no worse off than if it was builtin. In many use-cases, you won't even need a wrapper function, because the bounds won't be changing, or will change only rarely. So you only need test them once, not on every call to clamp. Win! I respect your right to check the bounds for NANs. How about you respect my right to not to, and don't force me to do it *twice* to get the behaviour I want? > Just as an exception can be suppressed by explicit code, Nan poisoning can > be suppressed by explicit checks. What you want is for people who want to test for NANs to have the clamp function do it for them, and people who don't want to check for NANs to have to do it twice, once in their wrapper function, and once in the clamp function. Your attitude here is literally: "Oh, you don't want to check for NANs? Then I'll make you do it twice as much as everyone else!" > So let me rewrite your second and third > paragraphs above (recall Option 1 which you favor is ignore NaNs, and > Option 2 is NaN poisoning): > > Let's say the stdlib uses Option 2. The function doesn't need to do any > explicit checks for NANs, But that's not true, it does need to check for NANs explicitly, because order comparisons `x < NAN` don't return NANs. There may be some clever arrangement of arguments for min and max that will return a NAN, but that's depending on accidental behaviour. You can't rely on it. (Having the result of min and max depend on the order of arguments is not a feature, and relying on that accidental behaviour is not safe.) -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message
[Python-ideas] Re: Add builtin function for min(max())
Sorry, that got sent too soon. On Sun, Jul 5, 2020 at 1:59 PM Christopher Barker wrote: > On Sun, Jul 5, 2020 at 6:15 AM MRAB wrote: > >> > clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: >> Union[Number, Iterable[Number]]) >> > > > What would that return? What if the iterables were two different > lengths? > > If anything, I would accept an iterable for the value, and return an > iterator. > > min() with an iterable is essentially a reduce. clamp() with an iterable > would be a map. > Though then there is the question of what to return for a scalar value: an iterator with one value or a scalar? So maybe these kinds of operations should be left to numpy. -CHB ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/NC334DSLOP72P5EABIEVNPLXIBLZWU7A/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 2020-07-05 14:06, MRAB wrote: On 2020-07-05 10:09, Federico Salerno wrote: [snip] FInally, I'd like to lit another fire: given that `min()` and `max()` accept an arbitrary amount of arguments, and that the signature that seems to be preferred for the hypothetical clamp at the moment sees `value` as the first positional argument, should the function then accept iterables as values for `minimum` and `maximum`? Something along the lines of: clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: Union[Number, Iterable[Number]]) I think that's overcomplicating it. How often have you actually wanted that feature? If you want bounds that are iterables, just use min/max on them first. Another point: min and max accept either a single iterable or multiple values, but not a mixture, so they set a precedent for 'clamp' not accepting a mixture too. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/OEHVQXY2JT6ESPRJ2K7RX2RQ4RJCOHLH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 05/07/2020 10:09, Federico Salerno wrote: On the topic of NaNs: I think in the face of ambiguity, we should refuse the temptation to guess and raise ValueError when the values given are not comparable to the point of clearly determining whether `value` is or isn't within `minimum` and `maximum` or which of the two bounds it exceeds. It is the programmer's responsibility to ensure they supply arguments that make sense, and non-numbers should be considered exceptional behaviour: as such, the programmer that anticipates those kinds of values should handle them exceptionally. About the name: clamp seems to be the most favoured name and the discussion convinced me it's the one that should make it to the eventual proposal. About the stdlib/builtin status: `min(max(x, min_), max_)` is a common enough idiom for a simple enough function that I think it is definitely beneficial and in no way dangerous to have, and that any status other than builtin would incur too much overhead for something so small. I risk claiming that most calls to max() and min() occur in modules that do not `import math` (or at the very least, they occur often enough without `import math`), and I believe clamp(), being very similar in scope to those, should benefit from similar status. I don't think clamp is a common enough identifier in non-specific fields to disqualify its implementation as a builtin by itself. By contrast, terms like `min` and `max` are extremely common in pretty much all contexts, and yet we've all survived just fine by typing `min_` and `max_` or even shadowing the names altogether (which I prefer not to do, but is definitely an option). +1 to all of the above (I don't feel strongly about the name). All seems very sensible. FInally, I'd like to lit another fire: given that `min()` and `max()` accept an arbitrary amount of arguments, and that the signature that seems to be preferred for the hypothetical clamp at the moment sees `value` as the first positional argument, should the function then accept iterables as values for `minimum` and `maximum`? Something along the lines of: clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: Union[Number, Iterable[Number]]) -1. As others have said, this is over-egging it. I think None should be allowed as a missing bound. I don't think the new function should be restricted to numbers. There may be uses for strings, or for user-built classes; why restrict it unnecessarily? If it quacks like supporting __lt__ and __gt__, it's a duck. Rob Cliffe ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/YUOCR36ZBUGUDTHJ3HDBIEYFSUVHCXX7/ Code of Conduct: http://python.org/psf/codeofconduct/ ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/2WWV33TF5C5H7HXU7ETMTIOIWM3NU75P/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020, 3:51 PM Chris Angelico wrote: > On Mon, Jul 6, 2020 at 2:15 AM David Mertz wrote: > > > > This is a digression, but does anyone have a nice example IN PYTHON of > arriving at a NaN without going through infinity. I think Julia is right > and Python is wrong about '0/0', but as things are, that's not an example. > > > > Not sure why "without going through infinity" is relevant, but you can > always just use float("nan") to get one, and I'm sure there are other > calculations that result in nan. It's just that 0/0 (like any other > operation that involves division by zero, including 0**-1) immediately > raises, rather than silently returning a nan. > Like I said, digression. I teach ieee-754 pretty often, or at least touch on it. I want to demonstrate to students that they might have NaN values to consider. Constructing one purely artificially with 'float("nan")' doesn't make the point well. Some operation that ends up with overflow infinities that are divided or subtracted is OK. But it would be nice to show a clean example where NANs arise without infinities arising first. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/EUL4LL2WYRAH2TMYEAGAJMT3WTODWIX6/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 6:15 AM MRAB wrote: > > clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: > Union[Number, Iterable[Number]]) > > Ss ( IsA Zzz What would that return? What if the iterable were two different lengths? If anything, I would accept an iterable for value, and return an iterator. Min() with an iterable is essential a reduce. Clamp() with an iterable would be > I think that's overcomplicating it. How often have you actually wanted > that feature? > > If you want bounds that are iterables, just use min/max on them first. > ___ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/QCP347S4JF4COOCCVNALCH7XBNBINF5A/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/I7MNWPD3BPXJOWCADD6QOJBK4UYUXFX7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Mon, Jul 6, 2020 at 2:15 AM David Mertz wrote: > > This is a digression, but does anyone have a nice example IN PYTHON of > arriving at a NaN without going through infinity. I think Julia is right and > Python is wrong about '0/0', but as things are, that's not an example. > Not sure why "without going through infinity" is relevant, but you can always just use float("nan") to get one, and I'm sure there are other calculations that result in nan. It's just that 0/0 (like any other operation that involves division by zero, including 0**-1) immediately raises, rather than silently returning a nan. ChrisA ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/YZBMLNWSJLGG7ZNTRZ4YKOCALUTXDLNQ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 8:57 AM Steven D'Aprano wrote: > > In the absense of any clear winner, my position is that NAN poisoning > should be opt-in. We should pick the option which inconveniences people > who want the other the least . > > Let's say the stdlib uses Option 1. The function doesn't need to do any > explicit checks for NANs, so there's no problem with large integers > overflowing, or Decimals raising ValueError, or any need to do a > conversion to float. > > People who want NAN poisoning can opt-in by doing a check for NANs > themselves, either in a wrapper function, or by testing the bounds > *once* ahead of time and then just calling the stdlib `clamp` once they > know they aren't NANs. Imagine making the same statement about exceptions: Exceptions being raised should be opt-in. That sounds crazy but it's not. Before exceptions were commonplace, there were three possibilities when unreasonable operations were performed: - return some arbitrary or random value (not a NaN because they hadn't been invented); - and also set an "error flag" that could be checked by the caller to determine if something had gone wrong (but frequently was not); - terminate the program. Things are much better now. Few argue that it was better before. Think of NaN as the value equivalent of an exception. NaN poisoning is the equivalent of the fact that any function that doesn't catch an exception passes it through. I don't usually write code that *uses *NaNs directly. If I want a distinguished non-numeric value, I use None or some other sentinel. If a NaN is produced by my code it indicates a bug. NaN poisoning increases the chance that a NaN generated somewhere won't be hidden by later code that manipulates that value. Why would I want to suppress that? Just as an exception can be suppressed by explicit code, Nan poisoning can be suppressed by explicit checks. So let me rewrite your second and third paragraphs above (recall Option 1 which you favor is ignore NaNs, and Option 2 is NaN poisoning): Let's say the stdlib uses Option 2. The function doesn't need to do any > explicit checks for NANs, so there's no problem with large integers > overflowing, or Decimals raising ValueError, causing errors that don't > get noticed, or any need to do a conversion to float. > > People who don't want NAN poisoning can opt-out by doing a check for NANs > themselves, either in a wrapper function, or by testing the bounds > *once* ahead of time and then not calling the stdlib `clamp` once they > know they are NANs. This is a better argument. People that use NaNs and expect them write code to handle it. The rest of us don't want to be surprised by suppressed errors. --- Bruce ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/X7RGOQWB5OOEXWKYL2VVPIBZ56YAYOAO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 05/07/2020 16:15, Steven D'Aprano wrote: Perhaps you should reconsider your expectations there. They do different things because they are different functions with different signatures and different purposes. It isn't even necessary to use min and max in the implementation of clamp, in fact it is better not to. Any "consistency" arguments for clamp versus min/max are weak at best. Point taken. I don't have a strong opinion on this but I'm curious if others would find it useful to have iterables as acceptable types for bounds. Or maybe even allowing a range instance to be supplied as bounds (I can't think of a use case where I couldn't just pass the bounds of the range instead, but maybe someone else can). ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/UVLZ2JWSH3OND6MJ3TPDFPQMLVSP4NO7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
Your original proposal appears to want this behavior: class BaseException: def __call__(self): raise self That could be expanded to something like: class BaseException: def __call__(self, *args): if not args: raise self if len(args) > 1: TypeError(f"{self} expects at most one argument")() # this adds yet another call level raise self from args[0] @staticmethod def reraise(): raise Why, though? One would usually want to raise the exception at the same call level of the invalid operation, not an extra one. Also, the raise statement makes it clear that something went wrong, and is easily recognized by static code analysers. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/P3AHT7LKQ5QATZN5KUJVMPUEVSYWF4OH/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
This is a digression, but does anyone have a nice example IN PYTHON of arriving at a NaN without going through infinity. I think Julia is right and Python is wrong about '0/0', but as things are, that's not an example. On Sun, Jul 5, 2020, 12:05 PM Chris Angelico wrote: > On Mon, Jul 6, 2020 at 1:58 AM Steven D'Aprano > wrote: > > Python makes it quite hard to get a NAN from the builtins, but other > > languuages do not. Here's Julia: > > > > julia> 0/0 > > NaN > > > > So there's at least one NAN which means *there is no correct answer*. > > >>> 1e1000-1e1000 > nan > > ChrisA > ___ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/TDIWUV4DCURDEKFMFVY2YZZWQ6ODWOFP/ > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/NZNMC3KSCKMBGIHXDJZPE5T4RI3TO3CE/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
On 2020-07-05 12:58 p.m., MRAB wrote: On 2020-07-05 14:10, Soni L. wrote: On 2020-07-05 10:03 a.m., MRAB wrote: On 2020-07-05 13:39, Soni L. wrote: 1. saves keywords and 2. can be passed as callables. since there's no lambda: raise, 2 is a new feature. How would you re-raise an exception? just call it. Wouldn't that just conflate raise with re-raise? raise x vs except: raise? just except foo: foo() What would be the replacement for: raise ex from None and so forth? no idea. just don't use that anymore? [snip] ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/SKPHKNJKLYN6QQWBEY2XIVRYANPUUS33/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Mon, Jul 6, 2020 at 1:58 AM Steven D'Aprano wrote: > Python makes it quite hard to get a NAN from the builtins, but other > languuages do not. Here's Julia: > > julia> 0/0 > NaN > > So there's at least one NAN which means *there is no correct answer*. >>> 1e1000-1e1000 nan ChrisA ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/TDIWUV4DCURDEKFMFVY2YZZWQ6ODWOFP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 2020-07-05 15:15, Steven D'Aprano wrote: [snip] The only differences I can see are that my implementation of clamp() supports None as a short-hand for infinity; and that it treats NANs according to the standard, unlike the builtin min and max, which manage to provide the worst of both possible words: they treat NANs according to the order of the arguments, thus satisfying nobody and annoying everybody. The first part is, I think, important because with the min+max idiom, if one side is unbounded, you can just leave it out: min(x, 1000) # like clamp(x, -float('inf'), 1000) but with clamp you have to supply *something* to mean "unbounded", and using float("inf") is not very convenient. So it's just a tiny bit of sugar to make the function more useful. +1 to using None. [snip] ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3GVTX4TM2Z5VZXQLBMJTJQS6S6FK76J5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
On 2020-07-05 14:10, Soni L. wrote: On 2020-07-05 10:03 a.m., MRAB wrote: On 2020-07-05 13:39, Soni L. wrote: 1. saves keywords and 2. can be passed as callables. since there's no lambda: raise, 2 is a new feature. How would you re-raise an exception? just call it. Wouldn't that just conflate raise with re-raise? What would be the replacement for: raise ex from None and so forth? no idea. just don't use that anymore? [snip] ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/XJNVGMBPF3W5HJN5A5TLQURYR4HPBWPE/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sat, Jul 04, 2020 at 09:11:34AM -0700, Ben Rudiak-Gould wrote: Quoting William Kahan, one of the people who designed IEEE-754 and NANs: > What he says there (on page 9) is > > >Some familiar functions have yet to be defined for NaN . For instance > >max{x, y} should deliver the same result as max{y, x} but almost no > >implementations do that when x is NaN . There are good reasons to > >define max{NaN, 5} := max{5, NaN} := 5 though many would disagree. > > It's clear that he's not referring to standard behavior here and I'm > not convinced that even he believes very strongly that min and max > should behave that way. Are you suggesting that Kahan *doesn't* believe that min() and max() should be symmetric? This is what Python does now: py> max(float('nan'), 1) nan py> max(1, float('nan')) 1 That's the sort of thing Kahan is describing, and it's clear to me that he thinks that's a bad thing. I will accept that treating NANs as missing values (as opposed to NAN-poisoning behaviour that returns a NAN if one of the arguments is a NAN) is open to debate. Personally, I don't think that there aren't many, or any, good use-cases for NAN-poisoning in this function. When we had this debate four years ago, I recall there was one person who suggested a use for it, but without going into details that I can recall. > NaN means "there may be a correct answer but I don't know what it is." That's one interpretation, but not the only one. Python makes it quite hard to get a NAN from the builtins, but other languuages do not. Here's Julia: julia> 0/0 NaN So there's at least one NAN which means *there is no correct answer*. In my younger days I was a NAN bigot who instisted that there was only one possible interpretation for NANs, but as I've gotten older I've accepted that treating them as *missing values* is acceptable. (Besides, like it or not, that's what a ton of software does.) With that interpretation, a NAN passed as the lower or upper bounds can be seen as another way of saying "no lower bounds" (i.e. negative infinity) or "no upper bounds" (i.e. positive infinity), not "some unknown bounds". > For example, evaluating (x**2+3*x+1)/(x+2) at x = -2 yields NaN. *cough* Did you try it? In Python it raises an exception; in Julia it returns -Inf. Substituting -2 gives -1/0 which under the rules of IEEE-754 should give -Inf. > The correct answer to the problem that yielded this formula is > probably -1, How do you get that conclusion? For (x**2+3*x+1)/(x+2) to equal -1, you would have to substitute either x=-3 or x=-1, not -2. py> x = -1; (x**2+3*x+1)/(x+2) -1.0 py> x = -3; (x**2+3*x+1)/(x+2) -1.0 [...] > It's definitely true that if plugging in any finite or infinite number > whatsoever in place of a NaN will yield the same result, then that > should be the result when you plug in a NaN. For example, clamp(x, > NaN, x) should be x for every x (even NaN), and clamp(y, NaN, x) where > y > x should be a ValueError (or however invalid bounds are treated). I think you are using the signature clamp(lower, value, upper) here. Is that right? I dislike that signature but for the sake of the argument I will use it in the following examples. I agree with you that `clamp(lower=x, value=NAN, upper= x)` should return x. I agree that we should raise if the bounds are in reverse order, e.g. clamp(lower=2, value=x, upper=1) I trust we agree that if the value is a NAN, and the bounds are not equal, we should return a NAN: clamp(1, NAN, 2) # return a NAN So I think we agree on all these cases. So I think there is only one point of contention: what to do if the bounds are NANs? There are two obvious, simple and reasonable behaviours: Option 1: Treat a NAN bounds as *missing data*, which effectively means "there is no limit", i.e. as if you had passed the infinity of the appropriate sign for the bounds. Option 2: Treat a NAN bounds as invalid, or unknown, in which case you want to return a NAN (or an exception). This is called "NAN poisoning". I will happily accept that people might reasonably want either behaviour. But unless we provide two implementations, we have to pick one or the other. Which should we pick? In the absense of any clear winner, my position is that NAN poisoning should be opt-in. We should pick the option which inconveniences people who want the other the least. Let's say the stdlib uses Option 1. The function doesn't need to do any explicit checks for NANs, so there's no problem with large integers overflowing, or Decimals raising ValueError, or any need to do a conversion to float. People who want NAN poisoning can opt-in by doing a check for NANs themselves, either in a wrapper function, or by testing the bounds *once* ahead of time and then just calling the stdlib `clamp` once they know they aren't NANs. If they use a wrapper function, they end up testing the bounds for NANs on
[Python-ideas] Re: Access (ordered) dict by index; insert slice
Steven D'Aprano writes: > Regarding your observation that dict views behave poorly if they > have unhashable values, I agree, it is both odd and makes them less > useful. Possibly at some point between the PEP and the release of > the feature something changed, or perhaps it's just an oversight. I'm not sure what you expect from views, though: Python 3.8.3 (default, May 15 2020, 14:39:37) >>> set([[1]]) Traceback (most recent call last): File "", line 1, in TypeError: unhashable type: 'list' >>> {'a' : [1]}.keys() <= {'a' : [1], 'b' : 2}.keys() True >>> {'a' : [1]}.values() <= {'a' : [1], 'b' : 2}.values() Traceback (most recent call last): File "", line 1, in TypeError: '<=' not supported between instances of 'dict_values' and 'dict_values' >>> {'a' : [1]}.items() <= {'a' : [1], 'b' : 2}.items() True So all of the above are consistent with the behavior of sets, except that items views do some part of comparisons themselves to deal with non-hashables which is an extension to set behavior. And values views don't pretend to be sets. The ValuesView ABC is not derived from Set, presumably because dict.values returns something like a multiset. Most set operations on key and item views seem to convert to set and where appropriate return set (which makes sense, since returning a view would require synthesizing a dict to be the view of!) This means you can't do set operations (except comparisons) on items views if any values aren't hashable. I'm not sure what I think about this: >>> {'a' : 1, 'b' : 2}.values() == {'b' : 2, 'a' : 1}.values() False That does seem less than useful. But I guess a multiset comparison requires an auxiliary data structure that can be sorted or a complicated, possibly O(n^2), comparison in place. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/3UBEDD3HPQ56KUI2BJRH4VVZTRZCTUXB/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
2qdxy4rzwzuui...@potatochowder.com writes: > On 2020-07-05 at 12:18:54 +0900, > "Stephen J. Turnbull" wrote: > > > Which suggests the question: Is there a commonly used equivalent for > > complex numbers? > > How would that work? Complex numbers are unordered, but I suspect that > you know that. Oh, that's not a problem. Impose one, and done. If you insist on two complex-parameter bounds, there's at least one interesting way to specify a total order with a connected "region" "between" any two complex numbers: lexicographic in (magnitude, argument). But my question was more "what's the use case?" So I'm not persuaded by thinking of confining the mouse pointer to a window whose points are represented by complex numbers. I was more wondering if, for example, it would be useful in working with electromagnetic waveforms, or such applications where for some reason the complex plane is more useful than the real one. But let's think bigger, much bigger. Really, clamp is a topological concept with a bounding *set*. What's not to love about clamp(z, Mandelbrot)? :-) ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/OT26JNLZTR5QPUW2EGPSRDOI562ZJ73O/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sat, Jul 04, 2020 at 01:01:15AM +0100, MRAB wrote: > Should it raise an exception if minimum > maximum? I think there are only two reasonable answers to this: - raise an exception if the lower bounds is greater than the upper bounds ("errors should never pass silently"); - or Do What I Mean by swapping them if they are in the wrong order: if lower > upper: lower, upper = upper, lower I'm +1 on raising and about +0.1 on DWIM. People who have read my posts on this mailing list in the past may remember that I am usually very suspicious of, if not hostile to, DWIM functions, but in this case I think it's harmless. This is what numpy does if you get the order wrong: py> import numpy as np py> np.clip(5, 1, 10) # This is correct. 5 py> np.clip(5, 10, 1) # WOT? 10 Silently returning garbage is not, in my opinion, acceptable here. -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/NJBJQSOCXBQ5PGXIP2Y5SFBQ25K46ZLC/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sat, Jul 04, 2020 at 10:16:45AM +0200, Federico Salerno wrote: > Yes, I'd expect ValueError if min > max or max < min. Is there a difference between those two conditions? *wink* > On 04/07/2020 02:03, Steven D'Aprano wrote: > >Bottom line is that passing a NAN as the lower or upper bound should > >treat it as equivalent to "unbounded", that is, equivalent to ±∞. The > >beauty of that is that it can be implemented without explicitly > >testing for NANs, which involves unnecessary conversions to float, and > >may even raise an exception. Here is the version I use: ... Features: > >* uses None as a convenient alias for unbounded; * treats NANs > >according to the standard; * requires no explicit conversion to float > >or testing for NANs; * so this will work with Fractions and Decimals. > > I'm not opposed to this but wouldn't the programmer expect it to behave > much like a shorthand of the existing min() + max()? For regular numeric numbers, it does. The only differences I can see are that my implementation of clamp() supports None as a short-hand for infinity; and that it treats NANs according to the standard, unlike the builtin min and max, which manage to provide the worst of both possible words: they treat NANs according to the order of the arguments, thus satisfying nobody and annoying everybody. The first part is, I think, important because with the min+max idiom, if one side is unbounded, you can just leave it out: min(x, 1000) # like clamp(x, -float('inf'), 1000) but with clamp you have to supply *something* to mean "unbounded", and using float("inf") is not very convenient. So it's just a tiny bit of sugar to make the function more useful. I've been using it for about four years, and it's nice to have. Having a short-cut for clamp is a good usability feature that costs very little (a couple of extra pointer comparisons to test for `is None`, which is cheap as it comes in Python). > Should these two > then be modified to exhibit the same behaviour? I'd find it inconsistent > if clamp() did but min() and max() didn't. Perhaps you should reconsider your expectations there. They do different things because they are different functions with different signatures and different purposes. It isn't even necessary to use min and max in the implementation of clamp, in fact it is better not to. Any "consistency" arguments for clamp versus min/max are weak at best. -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/6SLKNXMFPIH2UMR3SBQP7H2B7QXCYMUN/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
On Sun, Jul 05, 2020 at 10:10:01AM -0300, Soni L. wrote: > >What would be the replacement for: > > > > raise ex from None > > > >and so forth? > > no idea. just don't use that anymore? So your plan is to make Python less useful, less powerful, and be unable to do things that it can do now? Sounds great! Not. If you want a callable that raises: def throw(exception, *args): raise exception(*args) func = lambda x: throw(ValueError, 'bad value') if x < 0 else x+1 Problem solved. The best part of this is that this function is 100% backwards compatible all the way back to Python 1.0, and you don't have to wait until Python 3.10 or 3.11 to use it. -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/FLM64YJJ6X6NWCXO7HQW6FOSA776FUS2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
On 2020-07-05 10:03 a.m., MRAB wrote: On 2020-07-05 13:39, Soni L. wrote: 1. saves keywords and 2. can be passed as callables. since there's no lambda: raise, 2 is a new feature. How would you re-raise an exception? just call it. What would be the replacement for: raise ex from None and so forth? no idea. just don't use that anymore? I prefer the clarity of knowing that it's raising an exception and not just calling. Calls usually return. On 2020-07-05 1:15 a.m., Steven D'Aprano wrote: On Sun, Jul 05, 2020 at 12:48:08AM -0300, Soni L. wrote: > ValueError()() should be the same as raise ValueError() but with an > extra call level. > > and raise should be deprecated. Proposals that are given without justification should be rejected without justification: "No they shouldn't." If you feel like giving reasons for these changes other than "because I, Soni, say so", then I will consider the merits of those reasons before agreeing or disagreeing with the proposal. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/MFNOEEOUMRGJXM433DQQVT57S5ERM7U3/ Code of Conduct: http://python.org/psf/codeofconduct/ ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/D4ECM6WBYNRY2MX2FSAXI6HNNCW6L47R/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 2020-07-05 10:09, Federico Salerno wrote: [snip] FInally, I'd like to lit another fire: given that `min()` and `max()` accept an arbitrary amount of arguments, and that the signature that seems to be preferred for the hypothetical clamp at the moment sees `value` as the first positional argument, should the function then accept iterables as values for `minimum` and `maximum`? Something along the lines of: clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: Union[Number, Iterable[Number]]) I think that's overcomplicating it. How often have you actually wanted that feature? If you want bounds that are iterables, just use min/max on them first. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/QCP347S4JF4COOCCVNALCH7XBNBINF5A/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
On 2020-07-05 13:39, Soni L. wrote: 1. saves keywords and 2. can be passed as callables. since there's no lambda: raise, 2 is a new feature. How would you re-raise an exception? What would be the replacement for: raise ex from None and so forth? I prefer the clarity of knowing that it's raising an exception and not just calling. Calls usually return. On 2020-07-05 1:15 a.m., Steven D'Aprano wrote: On Sun, Jul 05, 2020 at 12:48:08AM -0300, Soni L. wrote: > ValueError()() should be the same as raise ValueError() but with an > extra call level. > > and raise should be deprecated. Proposals that are given without justification should be rejected without justification: "No they shouldn't." If you feel like giving reasons for these changes other than "because I, Soni, say so", then I will consider the merits of those reasons before agreeing or disagreeing with the proposal. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/MFNOEEOUMRGJXM433DQQVT57S5ERM7U3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 5, 2020 at 2:36 PM Federico Salerno wrote: > On the topic of NaNs: I think in the face of ambiguity, we should refuse > the temptation to guess and raise ValueError when the values given are not > comparable to the point of clearly determining whether `value` is or isn't > within `minimum` and `maximum` or which of the two bounds it exceeds. It is > the programmer's responsibility to ensure they supply arguments that make > sense, and non-numbers should be considered exceptional behaviour: as such, > the programmer that anticipates those kinds of values should handle them > exceptionally. > +1 > About the stdlib/builtin status: `min(max(x, min_), max_)` is a common > enough idiom for a simple enough function that I think it is definitely > beneficial and in no way dangerous to have, and that any status other than > builtin would incur too much overhead for something so small. I risk > claiming that most calls to max() and min() occur in modules that do not > `import math` (or at the very least, they occur often enough without > `import math`), and I believe clamp(), being very similar in scope to > those, should benefit from similar status. > > I don't think clamp is a common enough identifier in non-specific fields > to disqualify its implementation as a builtin by itself. By contrast, terms > like `min` and `max` are extremely common in pretty much all contexts, and > yet we've all survived just fine by typing `min_` and `max_` or even > shadowing the names altogether (which I prefer not to do, but is definitely > an option). > Has anyone suggested a .clamp method on the various numerical classes? Since this is a convenience that's easy to do without or implement yourself, I don't think it's important that it's super general and can instantly be used with anything comparable. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/GQGN3BYHJLCRDL4NZ2NSCI4F26TF5S4W/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: exception instance call should raise exception
1. saves keywords and 2. can be passed as callables. since there's no lambda: raise, 2 is a new feature. On 2020-07-05 1:15 a.m., Steven D'Aprano wrote: On Sun, Jul 05, 2020 at 12:48:08AM -0300, Soni L. wrote: > ValueError()() should be the same as raise ValueError() but with an > extra call level. > > and raise should be deprecated. Proposals that are given without justification should be rejected without justification: "No they shouldn't." If you feel like giving reasons for these changes other than "because I, Soni, say so", then I will consider the merits of those reasons before agreeing or disagreeing with the proposal. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/WZGPUJ3D6PCKMYXEXUA7W3KD4AFV5W65/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On the topic of NaNs: I think in the face of ambiguity, we should refuse the temptation to guess and raise ValueError when the values given are not comparable to the point of clearly determining whether `value` is or isn't within `minimum` and `maximum` or which of the two bounds it exceeds. It is the programmer's responsibility to ensure they supply arguments that make sense, and non-numbers should be considered exceptional behaviour: as such, the programmer that anticipates those kinds of values should handle them exceptionally. About the name: clamp seems to be the most favoured name and the discussion convinced me it's the one that should make it to the eventual proposal. About the stdlib/builtin status: `min(max(x, min_), max_)` is a common enough idiom for a simple enough function that I think it is definitely beneficial and in no way dangerous to have, and that any status other than builtin would incur too much overhead for something so small. I risk claiming that most calls to max() and min() occur in modules that do not `import math` (or at the very least, they occur often enough without `import math`), and I believe clamp(), being very similar in scope to those, should benefit from similar status. I don't think clamp is a common enough identifier in non-specific fields to disqualify its implementation as a builtin by itself. By contrast, terms like `min` and `max` are extremely common in pretty much all contexts, and yet we've all survived just fine by typing `min_` and `max_` or even shadowing the names altogether (which I prefer not to do, but is definitely an option). FInally, I'd like to lit another fire: given that `min()` and `max()` accept an arbitrary amount of arguments, and that the signature that seems to be preferred for the hypothetical clamp at the moment sees `value` as the first positional argument, should the function then accept iterables as values for `minimum` and `maximum`? Something along the lines of: clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: Union[Number, Iterable[Number]]) ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/YUOCR36ZBUGUDTHJ3HDBIEYFSUVHCXX7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 05/07/2020 05:39, Steven D'Aprano wrote: On Sun, Jul 05, 2020 at 12:18:54PM +0900, Stephen J. Turnbull wrote: > and I'd like to toss a possible `coerce` Here my issue is that for me the *target* of a coercion should be a "single thing", which could be a type, but might also be a scalar. ... No, I agree. In computing, coerce nearly always means to coerce to a type, not to coerce to some range of values. "bound", or probably "bounded" (for the same reason we have "sorted"). "clamp" and "clip" sound to me like things you do to a waveform (with Schottky diodes!), so it works for me but I'm not sure it travels well. Elsewhere in the thread (tree) we're already calling arg[1:2] "bounds", so reading this as "the value of x bound[ed] by the range -1 to +5" seems natural. Or "limited" possibly? I'm +0 on the idea FWIW. I also find it difficult to read, but I tend to in-line it as ifs, in part for clarity. Jeff Allen ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/T7HC7CNOZAHZHLKB36OR3772MAICWIUG/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Access (ordered) dict by index; insert slice
On Wed, Jul 1, 2020 at 8:37 AM Stestagg wrote: > 1. ordered collections that have some set-like operators added for > convenience, (conceptually, if not exactly, class ...(Set, Sequence):) but > are missing a single method full Sequence interface (__getitem__) > or > 2. Sets that happen to have a stable/deterministic element order > > My opinion is that, as of Python 3.7, they are effectively 1, even if the > isinstance hooks haven't been updated. I can see why people may think of > them as 2. I don't have any desire to change minds on this :) > > Semantic quibbling aside, My opinions/reasoning on the different options > are the following: > as long as we are semantic quibbling (1) is not quite right -- they don't "have some set-like operators, they have the full set of them, and they they ARE Sets: In [44]: d = {"this": 4, "that": 23} In [45]: isinstance(d.keys(), Set) Out[45]: True But see another recent thread on this list - they don't have all the same methods as the builtin set() type. But the ABC doesn't specify those, so they don't need to. However, that doesn't mean that it's somehow critical for them not to grow some extra functionality -- they would still be Sets. * Add numeric `__getitem__` to `dict_*` view classes: > +1 - This restores code that used to work in python 2, and makese some > things a bit easier. The O(n) behaviour is not ideal, but in my opinion is > an acceptable compromise > well, not really -- it only lets some things work like they did in Py2: most code I've ported from py2 to py3 that I needed to wrap list() around the views needed more than indexing -- I usually needed the list itself to be a persistent, mutable Sequence, not a view. I'm +1 on on this, ;cause why not? but honestly , the only good use case I've seen is random.choice() -- and while I've needed that, I can't say I've needed it often. > * Add new method to dict class: > -1 This doesn't feel like a good solution to me. Rather than continue to > argue about the justification for why, let's just say its a personal > judgement > wqe neither, gut it's not just a personal taste -- a getter wouldn't work with random.choice, the only known use case :-) -- unless the new method returned a Sequence-like view that could be indexed. Granted, it would allow an easier way to get a random item, but not as slick as: random.choice(a_dict.items()) I think it was Oscar that pointed out that repeated indexing of a view would be worse performance wise than making a proper list -- so that *might* be considered an attractive nuisance. -CHB -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/RMFV2PJBFXI5QFT3L3K6G45VG4QGZVIY/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On Sun, Jul 05, 2020 at 06:35:38PM +1200, Greg Ewing wrote: > All in all, I think "clamp" is the best term for this. +1 -- Steven ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/6NNMNZSALHQKJVNMPZZWDGT63XDXCYLU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Add builtin function for min(max())
On 5/07/20 4:39 pm, Steven D'Aprano wrote: Complex numbers represent points on a plane; it is very common in graphical toolkits to need to clamp an object to within some window or other region of the plane, But graphical toolkits don't treat points as complex numbers. The question is whether there is a conventional generalisation of clamp() used in complex analysis. There isn't one that I know of. so that you don't (e.g.) drag your object outside of the document, or position it somewhere off screen where it is impossible for the user to click on. I wouldn't call this operation "clipping", though -- see below. There are two standard terms for this function: clamp and clip, depending on whether you view the operation as squashing the value into a range or cutting off the bits that don't fit. The notion of clipping in computer graphics is not really the same thing. If you're drawing a point clipped to a window, and it's outside the window, then you skip drawing it altogether, you don't move it to the boundary of the window. And if you're drawing a line that's partly inside and partly outside the window, you need to cut off the part that's outside -- but you can't do that by clamping the outside point to the window, you need to do something more complicated. Another data point: In OpenGL documentation, the operation of limiting colour values or texture coordinates to be within a certain range is called "clamping". All in all, I think "clamp" is the best term for this. -- Greg ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/VLSAYZ7GSIUNT7FGN5ZV4SDXX7RAFSQC/ Code of Conduct: http://python.org/psf/codeofconduct/