[issue36827] Overriding __new__ method with itself changes behaviour of the class
Alexey Muranov added the comment: I see that I am not the only one who got bitten by this unexpected behaviour (though the others might have not realised it). There is a question ["Creating a singleton in Python"][1] on StackOverflow which was posted in 2011 and by now has the total of 737 upvotes. Here is a code snippet from the question: class Singleton(object): _instance = None def __new__(class_, *args, **kwargs): if not isinstance(class_._instance, class_): class_._instance = object.__new__(class_, *args, **kwargs) return class_._instance class MyClass(Singleton, BaseClass): pass [1]: https://stackoverflow.com/q/6760685 Currently this does not work as expected, try: class Failed(Singleton): def __init__(self, _): pass Failed(42) # TypeError: object.__new__() takes exactly one argument ... There is a similar code snippet in the accepted [answer][2] with 507 upvotes: class Singleton(object): _instances = {} def __new__(class_, *args, **kwargs): if class_ not in class_._instances: class_._instances[class_] = super(Singleton, class_).__new__( class_, *args, **kwargs ) return class_._instances[class_] class MyClass(Singleton): pass [2]: https://stackoverflow.com/a/6798042 This does not work either, for the same reason. -- ___ Python tracker <https://bugs.python.org/issue36827> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue36827] Overriding __new__ method with itself changes behaviour of the class
Alexey Muranov added the comment: Here is an example of code where i got surprised by the current behaviour and had to apply some (ugly) workaround: https://gist.github.com/alexeymuranov/04e2807eb5679ac7e36da4454a58fa7e -- ___ Python tracker <https://bugs.python.org/issue36827> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue32768] object.__new__ does not accept arguments if __bases__ is changed
Alexey Muranov added the comment: There were problems with the use case for mutable bases that i posted (see #36827). Here is an updated version: https://gist.github.com/alexeymuranov/04e2807eb5679ac7e36da4454a58fa7e -- ___ Python tracker <https://bugs.python.org/issue32768> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue36827] Overriding __new__ method with itself changes behaviour of the class
Alexey Muranov added the comment: I've noticed some faults in my code examples: `super(__class__, __class__)` instead of a more appropriate `super(__class__, cls)`, forgotten `return` before `super(__class__, self).foo(*args, **kwarg)`, maybe there are more. I cannot edit previous comments, but this does not affect the main point. I've stumbled on this behaviour in a situation where it actually poses me a problem. However, here is some analogy: if a calculator returns 0 as the result of a multiplication of any number by 1, this cannot be justified by saying that no one needs to multiply numbers by 1 anyway. -- ___ Python tracker <https://bugs.python.org/issue36827> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue36827] Overriding __new__ method with itself changes behaviour of the class
Alexey Muranov added the comment: Incidentally, the documentation gives the following signature of __new__: object.__new__(cls[, ...]) which suggests a variable number of arguments. -- ___ Python tracker <https://bugs.python.org/issue36827> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue36827] Overriding __new__ method with itself changes behaviour of the class
Alexey Muranov added the comment: The issue is the following: i expect overriding a method with itself to not change behaviour of the class. I do not see how my understanding of `__new__` or its point could be relevant. Do we agree that overriding a method with itself should not change behaviour? Is there a more correct way to do it than def foo(self, *args, **kwarg): # possible extensions # ... super(__class__, self).foo(*args, **kwarg) (modified accordingly for class and static methods)? When I do not override `__new__`, I expect Python to use `object`'s `__new__` (or at least pretend that it does). Therefore there should be no difference in behaviour. -- ___ Python tracker <https://bugs.python.org/issue36827> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue36827] Overriding __new__ method with itself changes behaviour of the class
New submission from Alexey Muranov : I expect that overriding methods with themselves like in the following example should not change the behaviour of the class: class C: a = 1 def __init__(self, b): self.b = b def f(self, x): return x*self.a + self.b + 1 @classmethod def g(cls, y): return y*cls.a + 2 @staticmethod def h(z): return z + 3 class D(C): def f(self, *args, **kwargs): return super(__class__, self).f(*args, **kwargs) @classmethod def g(cls, *args, **kwargs): return super(__class__, cls).g(*args, **kwargs) @staticmethod def h(*args, **kwargs): return super(__class__, __class__).h(*args, **kwargs) c = C(7) d = D(7) assert c.f(42) == d.f(42) assert c.g(42) == d.g(42) assert c.h(42) == d.h(42) (Moreover, I expect to be able to extend superclass method this way.) However, this does not work with `__new__`: class C: def __init__(self, x): self.x = x print(x) class D(C): @staticmethod def __new__(*args, **kwargs): return super(__class__, __class__).__new__(*args, **kwargs) C(7) # fine D(7) # TypeError: object.__new__() takes exactly one argument I think this is not a desirable feature. I would call it a bug. By the way, I understand why `object`'s `__init__` can complain about a wrong number of arguments, but I do not see a point in making `object`'s `__new__` complain about it. Here is my current workaround: class T: @staticmethod def __new__(cls, *_args, **_kwargs): return object.__new__(cls) class E(C, T): @staticmethod def __new__(*args, **kwargs): return super(__class__, __class__).__new__(*args, **kwargs) C(42) # fine E(42) # fine A possibly related issue: #32768 (https://bugs.python.org/issue32768) -- components: Interpreter Core messages: 341705 nosy: alexey-muranov priority: normal severity: normal status: open title: Overriding __new__ method with itself changes behaviour of the class type: behavior versions: Python 3.7, Python 3.8 ___ Python tracker <https://bugs.python.org/issue36827> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue32768] object.__new__ does not accept arguments if __bases__ is changed
Alexey Muranov added the comment: Here is a use case for writable bases: https://stackoverflow.com/q/56007866 class Stateful: """ Abstract base class for "stateful" classes. Subclasses must implement InitState mixin. """ @staticmethod def __new__(cls, *args, **kwargs): super_new = super(__class__, __class__).__new__ # XXX: see https://stackoverflow.com/a/9639512 class CurrentStateProxy(cls.InitState): @staticmethod def _set_state(state_cls=cls.InitState): __class__.__bases__ = (state_cls,) class Eigenclass(CurrentStateProxy, cls): @staticmethod def __new__(cls, *args, **kwargs): cls.__new__ = None # just in case return super_new(cls, *args, **kwargs) return Eigenclass(*args, **kwargs) class StatefulThing(Stateful): class StateA: """First state mixin.""" def say_hello(self): print("Hello!") self.hello_count += 1 self._set_state(self.StateB) return True def say_goodbye(self): print("Another goodbye?") return False class StateB: """Second state mixin.""" def say_hello(self): print("Another hello?") return False def say_goodbye(self): print("Goodbye!") self.goodbye_count += 1 self._set_state(self.StateA) return True # This one is required by Stateful. class InitState(StateA): """Third state mixin -- the initial state.""" def say_goodbye(self): print("Why?") return False def __init__(self): self.hello_count = self.goodbye_count = 0 def say_hello_followed_by_goodbye(self): self.say_hello() and self.say_goodbye() # -- # ## Demo ## # -- if __name__ == "__main__": t1 = StatefulThing() t2 = StatefulThing() print("> t1, say hello:") t1.say_hello() print("> t2, say goodbye:") t2.say_goodbye() print("> t2, say hello:") t2.say_hello() print("> t1, say hello:") t1.say_hello() print("> t1, say hello followed by goodbye:") t1.say_hello_followed_by_goodbye() print("> t2, say goodbye:") t2.say_goodbye() print("> t2, say hello followed by goodbye:") t2.say_hello_followed_by_goodbye() print("> t1, say goodbye:") t1.say_goodbye() print("> t2, say hello:") t2.say_hello() print("---") print( "t1 said {} hellos and {} goodbyes." .format(t1.hello_count, t1.goodbye_count) ) print( "t2 said {} hellos and {} goodbyes." .format(t2.hello_count, t2.goodbye_count) ) # Expected output: # # > t1, say hello: # Hello! # > t2, say goodbye: # Why? # > t2, say hello: # Hello! # > t1, say hello: # Another hello? # > t1, say hello followed by goodbye: # Another hello? # > t2, say goodbye: # Goodbye! # > t2, say hello followed by goodbye: # Hello! # Goodbye! # > t1, say goodbye: # Goodbye! # > t2, say hello: # Hello! # --- # t1 said 1 hellos and 1 goodbyes. # t2 said 3 hellos and 2 goodbyes. -- nosy: +alexey-muranov ___ Python tracker <https://bugs.python.org/issue32768> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue32768] object.__new__ does not accept arguments if __bases__ is changed
Alexey Muranov added the comment: IMO "overriding" a method with itself should not change the behaviour. So it seems to me that the following is a bug: class C: def __init__(self, m): print(m) class D: @staticmethod def __new__(cls, *args, **kwargs): return super(__class__, __class__).__new__(cls, *args, **kwargs) def __init__(self, m): print(m) C(42) # fine D(42) # TypeError: object.__new__() takes exactly one argument Of course such overriding makes little sense in itself, but forbidding it makes even less sense and creates bugs in more complex scenarios. -- ___ Python tracker <https://bugs.python.org/issue32768> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
Re: Syntax for one-line "nonymous" functions in "declaration style"
On mer., Apr 3, 2019 at 6:00 PM, python-list-requ...@python.org wrote: On Wed, Apr 3, 2019 at 3:55 AM Alexey Muranov wrote: I clarified what i meant by an assignment, and i believe it to be a usual meaning. 1. `def` is not an assignment, there is no left-hand side or right-hand side. I was talking about the normal assignment by which anyone can bind any value to any variable. Actually, a 'def' statement DOES perform assignment. It does a bit more than that, but it definitely is assignment. You can easily check the CPython disassembly: A command that performs an assignment among other things is not an assignment command itself. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On mar., Apr 2, 2019 at 6:00 PM, python-list-requ...@python.org wrote: On Tue, Apr 2, 2019 at 1:43 AM Alexey Muranov wrote: > On Mon, Apr 1, 2019 at 3:52 PM Alexey Muranov gmail.com> > wrote: > > > > I only see a superficial analogy with `super()`, but perhaps it is > > because you did not give much details of you suggestion. > > No, it's because the analogy was not meant to be anything more than > superficial. Both are constructs of syntactic magic that aid > readability at > a high level but potentially obscure the details of execution (in > relatively unimportant ways) when examined at a low level. Since i understand that the "super() magic" is just evaluation in a predefined environment, it does not look so very magic. It's the reason why this doesn't work: superduper = super class A: def f(self): return 42 class B(A): def f(self): return superduper().f() B().f() Traceback (most recent call last): File "", line 1, in File "", line 3, in f RuntimeError: super(): __class__ cell not found But this does: class C(A): def f(self): return superduper().f() not super C().f() 42 I don't know, seems magical to me. Moreover, without this "magic", `super()` would have just produced an error. So this magic did not change behaviour of something that worked before, it made "magically" work something that did not work before (but i am still not excited about it). I'm curious how you feel about this example then (from the CPython 3.7.2 REPL; results from different Python implementations or from scripts that comprise a single compilation unit may vary)? 372 is 372 True b = 372; b is 372 True b = 372 b is 372 False > Maybe it was from my talk of implementing this by replacing the > assignment > with an equivalent def statement in the AST. Bear in mind that the def > statement is already just a particular kind of assignment: it creates > a > function and assigns it to a name. The only difference between the > original > assignment and the def statement that replaces it is in the __name__ > attribute of the function object that gets created. The proposal just > makes > the direct lambda assignment and the def "assignment" to be fully > equivalent. `def` is not an assignment, it is more than that. def is an assignment where the target is constrained to a single variable and the expression is constrained to a newly created function object (optionally "decorated" first with one or more composed function calls). The only ways in which: @decorate def foo(blah): return stuff is more than: foo = decorate(lambda blah: stuff) are: 1) the former syntactically allows statements inside the function body, not just expressions; 2) the former syntactically allows annotations on the function; and 3) the former syntactically sets a function name and the latter doesn't. In other words, all of the differences ultimately boil down to syntax. Sorry, i do not feel like continuing this discussion for much longer, or we need to concentrate on some specific statement on which we disagree. I clarified what i meant by an assignment, and i believe it to be a usual meaning. 1. `def` is not an assignment, there is no left-hand side or right-hand side. I was talking about the normal assignment by which anyone can bind any value to any variable. 2. If i execute an assignment statement foo = ... and instead of evaluating the right-hand side and assigning the value to "foo" variable Python does something else, i consider the assignment operation ( = ) broken, as it does not do assignment (and only assignment). I've said more on this in previous messages. 3. About the examples with `372 is 372`, Python gives no garanties about the id's of numerical objects, and about id's of many other types of immutable objects. The user is not supposed to rely on their equality or inequality. Anytime Python's interpreter encounter two immutable objects that it finds identical, it is free to allocate a single object for both, this does not change the guaranteed semantics of the program. The '__name__' attribute of an object, as well as most (or all) other attributes, is a part of object's value/contents, no analogies with the id's. I am sorry, but except maybe for one or two more very specific questions, I am probably not going to continue. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On Mon, Apr 1, 2019 at 3:52 PM Alexey Muranov gmail.com> wrote: > > I only see a superficial analogy with `super()`, but perhaps it is > because you did not give much details of you suggestion. No, it's because the analogy was not meant to be anything more than superficial. Both are constructs of syntactic magic that aid readability at a high level but potentially obscure the details of execution (in relatively unimportant ways) when examined at a low level. Since i understand that the "super() magic" is just evaluation in a predefined environment, it does not look so very magic. I do not know if Python can already manipulate blocks of code and environments as first-class objects, but in any case this does not look to be too far from the its normal behaviour/semantics. Moreover, without this "magic", `super()` would have just produced an error. So this magic did not change behaviour of something that worked before, it made "magically" work something that did not work before (but i am still not excited about it). On the contrary, i have no idea of how in the current semantics executing an assignment can mutate the assigned value. > On the other hand, i do use assignment in Python, and you seem to > propose to get rid of assignment or to break it. I thought the proposal was clear and succinct. "When [lambda expressions] are directly assigned to a variable, Python would use the variable name as the function name." That's all. I don't know where you got the idea I was proposing "to get rid of assignment". I suppose we use the term "assignment operation" differently. By assignment i mean evaluating the expressions in the right-hand side and assigning (binding?) the value to the variable or location described in the left-hand side. I believed this was the usual meaning of "assignment"... The behaviour you describe cannot happen during assignment in this sense. Maybe it was from my talk of implementing this by replacing the assignment with an equivalent def statement in the AST. Bear in mind that the def statement is already just a particular kind of assignment: it creates a function and assigns it to a name. The only difference between the original assignment and the def statement that replaces it is in the __name__ attribute of the function object that gets created. The proposal just makes the direct lambda assignment and the def "assignment" to be fully equivalent. `def` is not an assignment, it is more than that. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Generator definition syntax (was: Syntax for one-line "nonymous" functions)
On mar., Apr 2, 2019 at 4:31 AM, python-list-requ...@python.org wrote: Re: ">> Neither i like how a function magically turns into a generator if the keyword `yield` appears somewhere within its definition. I agree, there should have been a required syntactic element on the "def" line as well to signal it immediately to the reader. It won't stop me from using them, though." One way to save people looking at the code from having to look through a function for a yield statement to see if it is a generator would be to add a """doc string""" immediately after the function def, saying that it is a generator and describing what it does. I realize I'm calling on the programmer to address this issue by adding doc strings. Nonetheless adding doc strings is a good habit to get in to. --- Joseph S. And even if Python did not have docstrings, the programmer could still use comments to tell a fellow programmer what kind of code the fellow programmer is looking at. Even languages like Brainfuck have comments :). Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On lun., avril 1, 2019 at 6:00 PM, python-list-requ...@python.org wrote: On Sun, Mar 31, 2019 at 1:09 PM Alexey Muranov wrote: On dim., Mar 31, 2019 at 6:00 PM, python-list-requ...@python.org wrote: > On Sat, Mar 30, 2019, 5:32 AM Alexey Muranov > > wrote: > >> >> On ven., Mar 29, 2019 at 4:51 PM, python-list-requ...@python.org >> wrote: >> > >> > There could perhaps be a special case for lambda expressions such >> > that, >> > when they are directly assigned to a variable, Python would use >> the >> > variable name as the function name. I expect this could be >> > accomplished by >> > a straightforward transformation of the AST, perhaps even by just >> > replacing >> > the assignment with a def statement. >> >> If this will happen, that is, if in Python assigning a >> lambda-defined >> function to a variable will mutate the function's attributes, or >> else, >> if is some "random" syntactically-determined cases >> >> f = ... >> >> will stop being the same as evaluating the right-hand side and >> assigning the result to "f" variable, it will be a fairly good extra >> reason for me to go away from Python. >> > > Is there a particular reason you don't like this? It's not too > different > from the syntactic magic Python already employs to support the > 0-argument > form of super(). I do not want any magic in a programming language i use, especially if it breaks simple rules. I do not like 0-argument `super()` either, but at least I do not have to use it. Well, you wouldn't have to use my suggestion either, since it only applies to assignments of the form "f = lambda x: blah". As has already been stated, the preferred way to do this is with a def statement. So just use a def statement for this, and it wouldn't affect you (unless you *really* want the function's name to be "" for some reason). I only see a superficial analogy with `super()`, but perhaps it is because you did not give much details of you suggestion. Not only i do not have to use `super()` (i do not have to use Python either), but the magic behaviour of `super` is explained by special implicit environments in which some blocks of code are executed. Though this looks somewhat hackish, it gives me no clue of how your idea of mutating objects during assignment is supposed to work. On the other hand, i do use assignment in Python, and you seem to propose to get rid of assignment or to break it. Note that foo.bar = baz and foo[bar] = baz are not assignments but method calls, but foo = bar it an assignment (if i understand the current model correctly). Do you propose to desugar it into a method/function call and to get rid of assignments in the language completely? Will the user be able to override this method? Something like: setvar("foo", bar) # desugaring of foo = bar Would the assignment operation remain in the language under a different name? Maybe, foo <- bar ? I am so perplexed by the proposed behaviour of `f = lambda...`, that i need to ask the followng: am i right to expact that 1. f = lambda x: x, g = lambda x: x*x 2. (f, g) = (lambda x: x, lambda x: x*x) 3. (f, g) = _ = (lambda x: x, lambda x: x*x) 4. f = (lambda x: x)(lambda x: x) g = (lambda x: x)(lambda x: x*x) Will all have the same net effect? I suppose in any case that return lambda x: and result = lambda x: return result would not return the same result, which is not what i want. I tried to imagine what semantics of the language could cause your proposed behaviour of `f = lambda...` and couldn't think of anything short of breaking the language. That said, that's also the reason why this probably wouldn't happen. Why go to the trouble of fixing people's lambda assignments for them when the preferred fix would be for them to do it themselves by replacing them with def statements? It is not fixing, it is breaking. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On dim., Mar 31, 2019 at 6:00 PM, python-list-requ...@python.org wrote: On Sat, Mar 30, 2019, 5:32 AM Alexey Muranov wrote: On ven., Mar 29, 2019 at 4:51 PM, python-list-requ...@python.org wrote: > > There could perhaps be a special case for lambda expressions such > that, > when they are directly assigned to a variable, Python would use the > variable name as the function name. I expect this could be > accomplished by > a straightforward transformation of the AST, perhaps even by just > replacing > the assignment with a def statement. If this will happen, that is, if in Python assigning a lambda-defined function to a variable will mutate the function's attributes, or else, if is some "random" syntactically-determined cases f = ... will stop being the same as evaluating the right-hand side and assigning the result to "f" variable, it will be a fairly good extra reason for me to go away from Python. Is there a particular reason you don't like this? It's not too different from the syntactic magic Python already employs to support the 0-argument form of super(). I do not want any magic in a programming language i use, especially if it breaks simple rules. I do not like 0-argument `super()` either, but at least I do not have to use it. I am suspicious of `__class__` too. But here only identifiers are hacked, not the assignment operator. (I suppose the hack can be unhacked by using your own meta-class with a custom `__prepare__`.) Neither i like how a function magically turns into a generator if the keyword `yield` appears somewhere within its definition. Those are the things i don't like the most in Python. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On ven., Mar 29, 2019 at 4:51 PM, python-list-requ...@python.org wrote: On Thu, Mar 28, 2019 at 2:30 PM Alexey Muranov wrote: On jeu., mars 28, 2019 at 8:57 PM, Terry Reedy wrote: > Throwing the name away is foolish. Testing functions is another > situation in which function names are needed for proper report. My idea however was to have it as an exact synonyme of an assignment of a lambda. Assignment is an assignment, it should not modify the attributs of the value that is being assigned. There could perhaps be a special case for lambda expressions such that, when they are directly assigned to a variable, Python would use the variable name as the function name. I expect this could be accomplished by a straightforward transformation of the AST, perhaps even by just replacing the assignment with a def statement. If this will happen, that is, if in Python assigning a lambda-defined function to a variable will mutate the function's attributes, or else, if is some "random" syntactically-determined cases f = ... will stop being the same as evaluating the right-hand side and assigning the result to "f" variable, it will be a fairly good extra reason for me to go away from Python. Since this could just as easily be applied to lambda though, I'm afraid it doesn't offer much of a case for the "f(x)" syntactic sugar. I did not get this. My initial idea was exactly about introducing a syntactic sugar for better readability. I've already understood that the use cases contradict PEP 8 recommendations. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Python-list Digest, Vol 186, Issue 31
On ven., Mar 29, 2019 at 4:51 PM, python-list-requ...@python.org wrote: On Thu, Mar 28, 2019 at 2:30 PM Alexey Muranov wrote: On jeu., mars 28, 2019 at 8:57 PM, Terry Reedy wrote: > Throwing the name away is foolish. Testing functions is another > situation in which function names are needed for proper report. My idea however was to have it as an exact synonyme of an assignment of a lambda. Assignment is an assignment, it should not modify the attributs of the value that is being assigned. There could perhaps be a special case for lambda expressions such that, when they are directly assigned to a variable, Python would use the variable name as the function name. I expect this could be accomplished by a straightforward transformation of the AST, perhaps even by just replacing the assignment with a def statement. If this will happen, that is, if in Python assigning a lambda-defined function to a variable will mutate the function's attributes, or else, if is some "random" syntactically-determined cases f = ... will stop being the same as evaluating the right-hand side and assigning the result to "f" variable, it will be a fairly good extra reason for me to go away from Python. Since this could just as easily be applied to lambda though, I'm afraid it doesn't offer much of a case for the "f(x)" syntactic sugar. I did not get this. My initial idea was exactly about introducing a syntactic sugar for better readability. I've already understood that the use cases contradict PEP 8 recommendations. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On jeu., mars 28, 2019 at 5:00 PM, python-list-requ...@python.org wrote: So documentation of that syntax would 100% be required Regarding documentation, i believe there would be 3 line to add: () = is a syntactic sugar for = lambda : Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On jeu., mars 28, 2019 at 8:57 PM, Terry Reedy wrote: On 3/28/2019 12:29 PM, Alexey Muranov wrote: On jeu., Mar 28, 2019 at 5:00 PM, python-list-requ...@python.org wrote: So my opinion is that lambda expressions should only be used within larger expressions and never directly bound. It would be however more convenient to be able to write instead just f(x) = x*x Given my view above, this is, standing alone, strictly an abbreviation of the equivalent def statement. I am presuming that a proper implementation would result in f.__name__ == 'f'. No, after some thought, i think it should be an abbreviation of "f = lambda x: x*x", f.__name__ would still be ''. Throwing the name away is foolish. Testing functions is another situation in which function names are needed for proper report. My idea however was to have it as an exact synonyme of an assignment of a lambda. Assignment is an assignment, it should not modify the attributs of the value that is being assigned. But i see your point about never assigning lambdas directly, it makes sense. But sometimes i do assign short lambdas directly to variable. Is the convenience and (very low) frequency of applicability worth the inconvenience of confusing the meaning of '=' and complicating the implementation? I do not see any conflicts with the existing syntax. It heavily conflicts with existing syntax. The current meaning of target_expression = object_expression is 1. Evaluate object_expression in the existing namespace to an object, prior to any new bindings and independent of the target_expression. 2. Evaluate target_expression in the existing namespace to one or more targets. 3. Bind object to target or iterate target to bind to multiple targets. I do not thick so. In "x = 42" the variable x is not evaluated. All examples of the proposed syntax i can think of are currently illegal, so i suppose there is no conflicts. (I would appreciate a counterexample, if any.) You are talking about syntax conflicts, I am talking about semantic conflict, which is important for human understanding. Thanks for the reference to PEP 8, this is indeed an argument against. The situation in which assigning lambda expressions is more tempting is when assigning to attributes or dicts. def double(x): return x*x C.double = double d['double'] = double versus C.double = lambda x: x*x d['double'] = lambda x: x*x These are some of examples i had in mind as well: C.double(x) = x*x d['double'](x) = x*x Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On jeu., mars 28, 2019 at 8:57 PM, Terry Reedy wrote: But i see your point about never assigning lambdas directly, it makes sense. But sometimes i do assign short lambdas directly to variable. Is the convenience and (very low) frequency of applicability worth the inconvenience of confusing the meaning of '=' and complicating the implementation? I do not see any conflicts with the existing syntax. It heavily conflicts with existing syntax. The current meaning of target_expression = object_expression is 1. Evaluate object_expression in the existing namespace to an object, prior to any new bindings and independent of the target_expression. 2. Evaluate target_expression in the existing namespace to one or more targets. 3. Bind object to target or iterate target to bind to multiple targets. I do not thick so. In "x = 42" the variable x is not evaluated. All examples of the proposed syntax i can think of are currently illegal, so i suppose there is no conflicts. (I would appreciate a counterexample, if any.) You are talking about syntax conflicts, I am talking about semantic conflict, which is important for human understanding. I believe there is no semantic conflict either, or could you be more specific? Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On jeu., mars 28, 2019 at 5:00 PM, python-list-requ...@python.org wrote: On 2019-03-27 10:42 a.m., Paul Moore wrote: On Wed, 27 Mar 2019 at 12:27, Alexey Muranov wrote: On mer., mars 27, 2019 at 10:10 AM, Paul Moore wrote: On Wed, 27 Mar 2019 at 08:25, Alexey Muranov wrote: Whey you need a simple function in Python, there is a choice between a normal function declaration and an assignment of a anonymous function (defined by a lambda-expression) to a variable: def f(x): return x*x or f = lambda x: x*x It would be however more convenient to be able to write instead just f(x) = x*x Why? Is saving a few characters really that helpful? So much so that it's worth adding a *third* method of defining functions, which would need documenting, adding to training materials, etc, etc? Because i think i would prefer to write it this way. That's not likely to be sufficient reason for changing a language that's used by literally millions of people. (Almost no new documentation or tutorials would be needed IMHO.) Documentation would be needed to explain how the new construct worked, for people who either wanted to use it or encountered it in other people's code. While it may be obvious to you how it works, it likely won't be to others, and there will probably be edge cases you haven't considered that others will find and ask about. For what it's worth, if I encountered "f(x) = x * x" in code, my first thought would be that Python somehow added a way to return an assignable reference from a function, rather than this being an anonymous function declaration. So documentation of that syntax would 100% be required Alex The thing to the right of the assignment symbol represents a value (an object), but the thing to the left does not represent a value, it represents a place for a value. What would an "assignable reference" mean? Say, variable "x" holds an "assignable reference", what can be done next? Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On jeu., Mar 28, 2019 at 5:00 PM, python-list-requ...@python.org wrote: So my opinion is that lambda expressions should only be used within larger expressions and never directly bound. It would be however more convenient to be able to write instead just f(x) = x*x Given my view above, this is, standing alone, strictly an abbreviation of the equivalent def statement. I am presuming that a proper implementation would result in f.__name__ == 'f'. No, after some thought, i think it should be an abbreviation of "f = lambda x: x*x", f.__name__ would still be ''. But i see your point about never assigning lambdas directly, it makes sense. But sometimes i do assign short lambdas directly to variable. Is the convenience and (very low) frequency of applicability worth the inconvenience of confusing the meaning of '=' and complicating the implementation? I do not see any conflicts with the existing syntax. It heavily conflicts with existing syntax. The current meaning of target_expression = object_expression is 1. Evaluate object_expression in the existing namespace to an object, prior to any new bindings and independent of the target_expression. 2. Evaluate target_expression in the existing namespace to one or more targets. 3. Bind object to target or iterate target to bind to multiple targets. I do not thick so. In "x = 42" the variable x is not evaluated. All examples of the proposed syntax i can think of are currently illegal, so i suppose there is no conflicts. (I would appreciate a counterexample, if any.) Thanks for the reference to PEP 8, this is indeed an argument against. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On mer., Mar 27, 2019 at 5:00 PM, python-list-requ...@python.org wrote: On 27/03/19 09:21, Alexey Muranov wrote: Whey you need a simple function in Python, there is a choice between a normal function declaration and an assignment of a anonymous function (defined by a lambda-expression) to a variable: def f(x): return x*x or f = lambda x: x*x It would be however more convenient to be able to write instead just f(x) = x*x (like in Haskell and such). Have this idea been discussed before? I do not see any conflicts with the existing syntax. The following would also work: I don't know. Something like the following is already legal: f(x)[n] = x * n And it does something completly different. Thanks for pointing out this example, but so far i do not see any issue with this. Of course assignment (to an identifier) is a completely different type of operation than in-place mutation (of an object) with __setitem__, etc. In <...> [<...>] = <...> the part to the left of "[<...>]=" is an expression that is to be evaluated, and only its value matters. Here "[]=" can be viewed as a method call, which is distinguished by the context from "[]" method call (__getitem__). In = <...> the is not evaluated. I still think that ()...() = <...> is unambiguous. The following seems possible too: a[m][n](x)(y) = m*x + n*y It would be the same as a[m][n] = lambda x: lambda y: m*x + n*y Here a[m] is evaluated, and on the result the method "[]=" (__setitem__) is called. Basically, "()...()=" seems to technically fit all contexts where "=" fits... Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Syntax for one-line "nonymous" functions in "declaration style"
On mer., mars 27, 2019 at 10:10 AM, Paul Moore wrote: On Wed, 27 Mar 2019 at 08:25, Alexey Muranov wrote: Whey you need a simple function in Python, there is a choice between a normal function declaration and an assignment of a anonymous function (defined by a lambda-expression) to a variable: def f(x): return x*x or f = lambda x: x*x It would be however more convenient to be able to write instead just f(x) = x*x Why? Is saving a few characters really that helpful? So much so that it's worth adding a *third* method of defining functions, which would need documenting, adding to training materials, etc, etc? Because i think i would prefer to write it this way. (Almost no new documentation or tutorials would be needed IMHO.) Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Syntax for one-line "nonymous" functions in "declaration style"
Whey you need a simple function in Python, there is a choice between a normal function declaration and an assignment of a anonymous function (defined by a lambda-expression) to a variable: def f(x): return x*x or f = lambda x: x*x It would be however more convenient to be able to write instead just f(x) = x*x (like in Haskell and such). Have this idea been discussed before? I do not see any conflicts with the existing syntax. The following would also work: incrementer(m)(n) = n + m instead of incrementer = lambda m: lambda n: n + m Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: Problem/bug with class definition inside function definition
Sorry, i was confused. I would say that this mostly works as expected, though the difference between x = 42 class C: x = x # Works and def f2(a): class D: a = a # Does not work <<<<< return D is still surprising to me. Otherwise, probably the solution with def f(a): _a = a class D: a = _a return D is good enough, if Python does not allow to refer "simultaneously" to variables from different scopes if they have the same name. Alexey. On Tue, 8 May, 2018 at 12:21 AM, Alexey Muranov <alexey.mura...@gmail.com> wrote: To be more exact, i do see a few workarounds, for example: def f4(a): b = a class D: a = b # Works return D But this is not what i was hoping for. Alexey. On Tue, 8 May, 2018 at 12:02 AM, Alexey Muranov <alexey.mura...@gmail.com> wrote: I have discovered the following bug or problem: it looks like i am forced to choose different names for class attributes and function arguments, and i see no workaround. Am i missing some special syntax feature ? Alexey. --- x = 42 class C1: y = x # Works class C2: x = x # Works # --- def f1(a): class D: b = a # Works return D def f2(a): class D: a = a # Does not work <<<<< return D def f3(a): class D: nonlocal a a = a # Does not work either <<<<< return D # --- def g1(a): def h(): b = a # Works return b return h def g2(a): def h(): a = a # Does not work (as expected) return a return h def g3(a): def h(): nonlocal a a = a # Works return a return h # --- if __name__ == "__main__": assert C1.y == 42 assert C2.x == 42 assert f1(13).b == 13 try: f2(13) # NameError except NameError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') try: f3(13).a # AttributeError except AttributeError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') assert g1(13)() == 13 try: g2(13)() # UnboundLocalError except UnboundLocalError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') assert g3(13)() == 13 -- https://mail.python.org/mailman/listinfo/python-list
Re: Problem/bug with class definition inside function definition
To be more exact, i do see a few workarounds, for example: def f4(a): b = a class D: a = b # Works return D But this is not what i was hoping for. Alexey. On Tue, 8 May, 2018 at 12:02 AM, Alexey Muranov <alexey.mura...@gmail.com> wrote: I have discovered the following bug or problem: it looks like i am forced to choose different names for class attributes and function arguments, and i see no workaround. Am i missing some special syntax feature ? Alexey. --- x = 42 class C1: y = x # Works class C2: x = x # Works # --- def f1(a): class D: b = a # Works return D def f2(a): class D: a = a # Does not work <<<<< return D def f3(a): class D: nonlocal a a = a # Does not work either <<<<< return D # --- def g1(a): def h(): b = a # Works return b return h def g2(a): def h(): a = a # Does not work (as expected) return a return h def g3(a): def h(): nonlocal a a = a # Works return a return h # --- if __name__ == "__main__": assert C1.y == 42 assert C2.x == 42 assert f1(13).b == 13 try: f2(13) # NameError except NameError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') try: f3(13).a # AttributeError except AttributeError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') assert g1(13)() == 13 try: g2(13)() # UnboundLocalError except UnboundLocalError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') assert g3(13)() == 13 -- https://mail.python.org/mailman/listinfo/python-list
Problem/bug with class definition inside function definition
I have discovered the following bug or problem: it looks like i am forced to choose different names for class attributes and function arguments, and i see no workaround. Am i missing some special syntax feature ? Alexey. --- x = 42 class C1: y = x # Works class C2: x = x # Works # --- def f1(a): class D: b = a # Works return D def f2(a): class D: a = a # Does not work < return D def f3(a): class D: nonlocal a a = a # Does not work either < return D # --- def g1(a): def h(): b = a # Works return b return h def g2(a): def h(): a = a # Does not work (as expected) return a return h def g3(a): def h(): nonlocal a a = a # Works return a return h # --- if __name__ == "__main__": assert C1.y == 42 assert C2.x == 42 assert f1(13).b == 13 try: f2(13) # NameError except NameError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') try: f3(13).a # AttributeError except AttributeError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') assert g1(13)() == 13 try: g2(13)() # UnboundLocalError except UnboundLocalError: pass except Exception as e: raise Exception( 'Unexpected exception raised: ' '{}'.format(type(e).__name__) ) else: raise Exception('No exception') assert g3(13)() == 13 -- https://mail.python.org/mailman/listinfo/python-list
Re: replacing `else` with `then` in `for` and `try`
On Fri, 2017-11-03 at 22:03 +1100, Chris Angelico wrote: > On Fri, Nov 3, 2017 at 8:48 PM, Alexey Muranov <alexey.muranov@gmail. > com> wrote: > > 'Then' describes what happens next indeed, unless some > > extraordinary > > situation prevents it from happening, for example: > > > > try: > > go_to_the_bakery() > > then: > > buy_croissants(2) > > except BakeryClosed: > > go_to_the_grociery() > > buy_baguette(1) > > finally: > > come_back() > > > > I know this is a poor program example (why not to use a boolean > > return value > > instead of an exception, etc.), and i know that currently in Python > > `except` > > must precede `else`, it is just to illustrate the choice of terms. > > What is the semantic difference between that code and the same > without the "then:"? Chris, the semantic difference is that their meanings/behaviours are not identical (i imply that `then` here does what `else` currently does). I agree however that from practical viewpoint the difference will probably never be observable (unless the person enters the bakery and asks for croissants, but during this time the baker exits the bakery and closes it to go on vacation). I can try to think of a better example if you give me any good use-case for `else` in `try`. I have searched on-line, and on StackOverflow in particular, but didn't find anything better that this: * https://stackoverflow.com/a/6051978 People seem very shy when it comes to giving a real-life example of `else` in `try`. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: replacing `else` with `then` in `for` and `try`
On Thu, 2017-11-02 at 16:31 +, Jon Ribbens wrote: > On 2017-11-02, Steve D'Apranowrote: > > On Fri, 3 Nov 2017 12:39 am, Jon Ribbens wrote: > > > Why would we want to make the language worse? It is fairly > > > obvious > > > what 'else' means, > > > > Yes, obvious and WRONG. > > Nope, obvious and right. > I suppose that to continue this way we'd need at some point define somehow the meaning of "obvious." > > > whereas 'then' has an obvious meaning that is in > > > fact the opposite of what it would actually do. > > > > Er... is today opposite day? Because 'then' describes precisely > > what it > > actually does. > > No, 'then' describes the opposite of what it does. The word 'then' > implies something that always happens next, whereas 'else' conveys > the correct meaning, which is something that happens if the course > of the preceding piece of code did not go as expected. > Jon, i get from this that for you, when there is no exception in `try`, or no `break` in a loop, the things did not go as expected. Either we need to agree that what is "expected" is subjective, or agree on some kind of formal or informal common meaning for it, because i would not have put it this way. 'Then' describes what happens next indeed, unless some extraordinary situation prevents it from happening, for example: try: go_to_the_bakery() then: buy_croissants(2) except BakeryClosed: go_to_the_grociery() buy_baguette(1) finally: come_back() I know this is a poor program example (why not to use a boolean return value instead of an exception, etc.), and i know that currently in Python `except` must precede `else`, it is just to illustrate the choice of terms. Best regards, Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: replacing `else` with `then` in `for` and `try`
On Thu, 2017-11-02 at 08:21 +1100, Chris Angelico wrote: > > With try/except/else, it's "do this, and if an exception happens, do this, else do this". So else makes perfect sense. Indeed, i forgot about `except`. I agree that "try/then/except/finally" would be better than "try/except/then/finally", but "try/except/else/finally" does not make a perfect sense IMHO. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: replacing `else` with `then` in `for` and `try`
On Wed, 2017-11-01 at 21:30 +, Stefan Ram wrote: > > In languages like Algol 68, »then« is used for a clause > that is to be executed when the main condition of an > if-statement /is/ true, so this might cause some confusion. > sure, and `else` is used for a clause that is to be executed when the main condition of `if` is false. So, in try: do_something except: catch_exception else: continue_doing_something when no exception occurs in `do_something`, is `do_something` more true, or more false? Alexey. -- https://mail.python.org/mailman/listinfo/python-list
Re: replacing `else` with `then` in `for` and `try`
On Thu, 2017-11-02 at 08:29 +1100, Chris Angelico wrote: > On Thu, Nov 2, 2017 at 8:23 AM, Ned Batchelder> wrote: > > > > > > Apart from the questions of backward compatibility etc (Python is > > unlikely > > to ever go through another shift like the 2/3 breakage), are you > > sure "then" > > is what you mean? This won't print "end": > > > > for i in range(10): > > print(i) > > else: > > print(end) > > Well, it'll bomb with NameError when it tries to look up the *name* > end. But it will run that line of code - if you quote it, it will > work. You see how people are confused over "for ... else". Alexey. -- https://mail.python.org/mailman/listinfo/python-list
replacing `else` with `then` in `for` and `try`
Hello, what do you think about the idea of replacing "`else`" with "`then`" in the contexts of `for` and `try`? It seems clear that it should be rather "then" than "else." Compare also "try ... then ... finally" with "try ... else ... finally". Currently, with "else", it is almost impossible to guess the meaning without looking into the documentation. Off course, it should not be changed in Python 3, maybe in Python 4 or 5, but in Python 3 `then` could be an alias of `else` in these contexts. Alexey. -- https://mail.python.org/mailman/listinfo/python-list
[issue26645] argparse prints help messages to stdout instead of stderr by default
Alexey Muranov added the comment: My grep man page says --help Print a brief help message. but indeed there is no `--help` in usage message. Maybe this is a bug of the man page. Thanks for the explanation. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue26645> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue26645] argparse prints help messages to stdout instead of stderr by default
Alexey Muranov added the comment: Thanks for the explanation, this makes sense. I did not notice that argparse outputs to stderr if command line arguments are wrong, i was probably wrong when said it prints error messages to stdout. I did not notice indeed that there were no `-h` option in git. However, my grep version 2.5.1-FreeBSD outputs help to stderr even with `--help` option. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue26645> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue26645] argparse prints help messages to stdout instead of stderr by default
New submission from Alexey Muranov: I believe that printing help and usage messages to stdout is a design error. In stdout i expect to find the output of my program, not help or diagnostic messages. It is strange to see nothing printed on the screen (where stderr usually goes), and then to find help, usage, or *error* messages in the file where stdout was sent. (Yes, argparse prints even error messages to stdout by default). This issue has been discussed before because the implementation did not agree with the documentation: http://bugs.python.org/issue10728 I believe that the conclusion to adjust the documentation to the implementation was a mistake. P.S. Compare with the direction of the output of `grep -h` or `git -h`. -- components: Library (Lib) messages: 262491 nosy: Alexey Muranov priority: normal severity: normal status: open title: argparse prints help messages to stdout instead of stderr by default type: behavior versions: Python 3.5 ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue26645> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com