list…pushed, or something

I'm not sure if there's anything inherently wrong with this idea, and I am well aware how incredibly easy it is to implement as an extension of the built-ins, but, I find it very useful to have variations of list().append(obj) and set().add(obj) that return, obj. I've never come up with perfect method names; sometimes I go with past-tense versions, "added" and "appended" (or "pushed"). I often use these methods in places where performance is a factor, such as using a set() to filter repeats from an input sequence. I was thinking it may be worth considering adding it to core, or perhaps creating collections types with these features, so they are high performance and standardized. They can be particularly useful in generator recipes, etc. Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com

On 27Mar2013 19:29, Shane Green <shane@umbrellacode.com> wrote: | I'm not sure if there's anything inherently wrong with this idea, and I am well aware | how incredibly easy it is to implement as an extension of the built-ins, but, I find it | very useful to have variations of list().append(obj) and set().add(obj) that return, | obj. I've never come up with perfect method names; sometimes I go with past-tense | versions, "added" and "appended" (or "pushed"). I often use these methods in places | where performance is a factor, such as using a set() to filter repeats from an input | sequence. I don't suppose you could post example code? I suspect the thinking goes that functions/methods that do something shouldn't just be "identity" functions where f(x) == x. And if they are defined to be identity functions you may as well return None, since the calling code isn't learning anything new. At any rate, that would be part of my thinking, and for me it is enough to not favour the proposal without a better demo of where it is a win, or of how horribly I have misconstrued your suggestion. Cheers, -- If everyone is thinking alike, then someone isn't thinking. - Patton

Actually this was the value doing the mutating, i.e, the <thing> i pushed or added, would be returned as operation's output. I see what you're saying, and I wasn't thinking of chaining so much as being able to include the operation in a expression and, in particular, a generator scenario. Ordered sequence of unique values from sequence with possible repeats [seen.added(value) for value in sequence if value not in seen] * * again, please forgive the method names, I was hoping to crowd source something better ;-) Replaces workarounds like: [seen.setdefault(value, value) for value in sequence if value not in seen] or seen = dict(sequence); [unique.pop(value) for value in sequence if value in unique] Like I said, it's incredibly simple to just extend set and list and add these in user space. Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com On Mar 27, 2013, at 9:49 PM, Terry Reedy <tjreedy@udel.edu> wrote:

On Wed, Mar 27, 2013 at 10:11 PM, Shane Green <shane@umbrellacode.com>wrote:
[seen.added(value) for value in sequence if value not in seen] *
Here's an easy way to do it:
--- Bruce Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security

That's clever: even works for zero because it's returned by or as second false. Cool. So I suppose I have to come up with more examples now ;-) Actually, on that point, I actually think the seen.added(value) (with a better name) is quite a bit cleaner than the one using "or". Clever as it is, I think someone learning the language would flinch when they saw that… :-) Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com On Mar 27, 2013, at 10:28 PM, Bruce Leban <bruce@leapyear.org> wrote:

On Wed, Mar 27, 2013 at 10:48 PM, Shane Green <shane@umbrellacode.com>wrote:
Yes, I suppose it's a bit obscure but you're only going to use it in a case where you value brevity over clarity, right? The C comma operator which always returns the second value, not depending that the first value is false. You can write this in Python as: (foo, bar)[1] or is there some cleaner way to write that? #define comma and False or :-) --- Bruce Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security

Always makes me think of my favorite C snippet: if (attack = true) { launch_nukes(); } Well, I have to admit that I'm drawing a blank on all the great use cases I had in mind, and it didn't seem to light any particular fires with the list, so I'd say this isn't a compelling enough story to take anymore time with at the moment. If a good–and not obscure–example comes to mind, I'll send it out, otherwise, thanks for the feedback! Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com On Mar 27, 2013, at 10:58 PM, Bruce Leban <bruce@leapyear.org> wrote:

Yes, that would be a nice function. The unique items from a ordered sequence was just supposed to be an example of something you could do with the concept I was going for: push/add methods that returned the value pushed/added, so a 'list.pushed(value)' could replace value inline. Of course it's turning out the unique items may best example which, in and of itselft, isn't very compelling argument for my original idea because there are better ways to solve this problem, as you've pointed out. On Mar 28, 2013, at 8:15 AM, MRAB <python@mrabarnett.plus.com> wrote:

And I was suggesting something along these lines would be generally useful (if not pointlessly easy): class Set(set): __slots__ = () def added(self, value): super(Set, self).add(value) return value def unique(items): seen = Set() return (seen.added(item) for item in items if item not in seen) On Mar 28, 2013, at 8:15 AM, MRAB <python@mrabarnett.plus.com> wrote:

On 27 March 2013 23:29, Shane Green <shane@umbrellacode.com> wrote:
I understand that the equivalent methods in other languages - sometimes frameworks int hose languages - allow one to chain method calls on the parent object, so they can happly write things along: list().append(1).append(0).sort().append(2) Python style, as well placed on the thread is that methods that perform changes to the underlying object return None, thus not allowing such constructs to mutable objects - even though one can happily do something like: image_name = url.split("/")[-1].split(".")[0] You can easily have the former behavior if you wrap your object in a construct that, whenever a called method would return "None", returns the original object itself. That could be placed in a utility module - and probably there is even some "MyHacks" package on pypi with functionality like that. If a naive implementation fits your needs, this one would work: class Chain: def __init__(self, obj, root=None): self.__obj = obj def __getattr__(self, attr): val = getattr(self.__obj, attr) if callable(val): self.__callable = val return self return val def __call__(self, *args, **kw): val = self.__callable(*args, **kw) if val is None: return self return val ---------------
I'd be -0 for something like that on the stlib, though - but if it was there, I'd look around "functools" (but it is obviously more like an "objecttool") js -><-

Yes, these are good points. To be clear about one thing, though, what I was suggesting behaves very differently than the mechanism most other languages may use to enable chaining. Chaining is usually based around the operations on X, returning a reference to X after completion (of course this only makes sense for mutator methods, otherwise nothing would been done or gotten). Given my recommendation: X.pushed(Y) -> X IFF (and-only-if) Y is X. However, X.pushed(Y) -> Y is always true. The idea was not to be able chain invocations, but to be able to use theses operations inline in places the plain value, Y, would have appeared. It's such a trivial matter it's almost moot point anyhow... The only time "list.puhed(x)" wou On Mar 29, 2013, at 4:40 AM, Joao S. O. Bueno <jsbueno@python.org.br> wrote:

Shane Green writes:
FWIW, Steve McConnell (Code Complete) recommends that X.pushed(foo()) quite often should be written as foo_value = foo() # but with a descriptive name! X.pushed(foo_value) # sic, probably pushed -> push? even if "foo_value" is only used once. It's not like you save anything but one line by putting foo() inside the parentheses, it's just a name binding that is resolved by the compiler anyway. My understanding of Guido's decisions is that he agrees with McConnell on this point.

On 27Mar2013 19:29, Shane Green <shane@umbrellacode.com> wrote: | I'm not sure if there's anything inherently wrong with this idea, and I am well aware | how incredibly easy it is to implement as an extension of the built-ins, but, I find it | very useful to have variations of list().append(obj) and set().add(obj) that return, | obj. I've never come up with perfect method names; sometimes I go with past-tense | versions, "added" and "appended" (or "pushed"). I often use these methods in places | where performance is a factor, such as using a set() to filter repeats from an input | sequence. I don't suppose you could post example code? I suspect the thinking goes that functions/methods that do something shouldn't just be "identity" functions where f(x) == x. And if they are defined to be identity functions you may as well return None, since the calling code isn't learning anything new. At any rate, that would be part of my thinking, and for me it is enough to not favour the proposal without a better demo of where it is a win, or of how horribly I have misconstrued your suggestion. Cheers, -- If everyone is thinking alike, then someone isn't thinking. - Patton

Actually this was the value doing the mutating, i.e, the <thing> i pushed or added, would be returned as operation's output. I see what you're saying, and I wasn't thinking of chaining so much as being able to include the operation in a expression and, in particular, a generator scenario. Ordered sequence of unique values from sequence with possible repeats [seen.added(value) for value in sequence if value not in seen] * * again, please forgive the method names, I was hoping to crowd source something better ;-) Replaces workarounds like: [seen.setdefault(value, value) for value in sequence if value not in seen] or seen = dict(sequence); [unique.pop(value) for value in sequence if value in unique] Like I said, it's incredibly simple to just extend set and list and add these in user space. Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com On Mar 27, 2013, at 9:49 PM, Terry Reedy <tjreedy@udel.edu> wrote:

On Wed, Mar 27, 2013 at 10:11 PM, Shane Green <shane@umbrellacode.com>wrote:
[seen.added(value) for value in sequence if value not in seen] *
Here's an easy way to do it:
--- Bruce Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security

That's clever: even works for zero because it's returned by or as second false. Cool. So I suppose I have to come up with more examples now ;-) Actually, on that point, I actually think the seen.added(value) (with a better name) is quite a bit cleaner than the one using "or". Clever as it is, I think someone learning the language would flinch when they saw that… :-) Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com On Mar 27, 2013, at 10:28 PM, Bruce Leban <bruce@leapyear.org> wrote:

On Wed, Mar 27, 2013 at 10:48 PM, Shane Green <shane@umbrellacode.com>wrote:
Yes, I suppose it's a bit obscure but you're only going to use it in a case where you value brevity over clarity, right? The C comma operator which always returns the second value, not depending that the first value is false. You can write this in Python as: (foo, bar)[1] or is there some cleaner way to write that? #define comma and False or :-) --- Bruce Latest blog post: Alice's Puzzle Page http://www.vroospeak.com Learn how hackers think: http://j.mp/gruyere-security

Always makes me think of my favorite C snippet: if (attack = true) { launch_nukes(); } Well, I have to admit that I'm drawing a blank on all the great use cases I had in mind, and it didn't seem to light any particular fires with the list, so I'd say this isn't a compelling enough story to take anymore time with at the moment. If a good–and not obscure–example comes to mind, I'll send it out, otherwise, thanks for the feedback! Shane Green www.umbrellacode.com 408-692-4666 | shane@umbrellacode.com On Mar 27, 2013, at 10:58 PM, Bruce Leban <bruce@leapyear.org> wrote:

Yes, that would be a nice function. The unique items from a ordered sequence was just supposed to be an example of something you could do with the concept I was going for: push/add methods that returned the value pushed/added, so a 'list.pushed(value)' could replace value inline. Of course it's turning out the unique items may best example which, in and of itselft, isn't very compelling argument for my original idea because there are better ways to solve this problem, as you've pointed out. On Mar 28, 2013, at 8:15 AM, MRAB <python@mrabarnett.plus.com> wrote:

And I was suggesting something along these lines would be generally useful (if not pointlessly easy): class Set(set): __slots__ = () def added(self, value): super(Set, self).add(value) return value def unique(items): seen = Set() return (seen.added(item) for item in items if item not in seen) On Mar 28, 2013, at 8:15 AM, MRAB <python@mrabarnett.plus.com> wrote:

On 27 March 2013 23:29, Shane Green <shane@umbrellacode.com> wrote:
I understand that the equivalent methods in other languages - sometimes frameworks int hose languages - allow one to chain method calls on the parent object, so they can happly write things along: list().append(1).append(0).sort().append(2) Python style, as well placed on the thread is that methods that perform changes to the underlying object return None, thus not allowing such constructs to mutable objects - even though one can happily do something like: image_name = url.split("/")[-1].split(".")[0] You can easily have the former behavior if you wrap your object in a construct that, whenever a called method would return "None", returns the original object itself. That could be placed in a utility module - and probably there is even some "MyHacks" package on pypi with functionality like that. If a naive implementation fits your needs, this one would work: class Chain: def __init__(self, obj, root=None): self.__obj = obj def __getattr__(self, attr): val = getattr(self.__obj, attr) if callable(val): self.__callable = val return self return val def __call__(self, *args, **kw): val = self.__callable(*args, **kw) if val is None: return self return val ---------------
I'd be -0 for something like that on the stlib, though - but if it was there, I'd look around "functools" (but it is obviously more like an "objecttool") js -><-

Yes, these are good points. To be clear about one thing, though, what I was suggesting behaves very differently than the mechanism most other languages may use to enable chaining. Chaining is usually based around the operations on X, returning a reference to X after completion (of course this only makes sense for mutator methods, otherwise nothing would been done or gotten). Given my recommendation: X.pushed(Y) -> X IFF (and-only-if) Y is X. However, X.pushed(Y) -> Y is always true. The idea was not to be able chain invocations, but to be able to use theses operations inline in places the plain value, Y, would have appeared. It's such a trivial matter it's almost moot point anyhow... The only time "list.puhed(x)" wou On Mar 29, 2013, at 4:40 AM, Joao S. O. Bueno <jsbueno@python.org.br> wrote:

Shane Green writes:
FWIW, Steve McConnell (Code Complete) recommends that X.pushed(foo()) quite often should be written as foo_value = foo() # but with a descriptive name! X.pushed(foo_value) # sic, probably pushed -> push? even if "foo_value" is only used once. It's not like you save anything but one line by putting foo() inside the parentheses, it's just a name binding that is resolved by the compiler anyway. My understanding of Guido's decisions is that he agrees with McConnell on this point.
participants (8)
-
Bruce Leban
-
Cameron Simpson
-
Guido van Rossum
-
Joao S. O. Bueno
-
MRAB
-
Shane Green
-
Stephen J. Turnbull
-
Terry Reedy