Re: Using Vitalije's code patterns
On Wed, Jan 29, 2020 at 11:10 PM Thomas Passin wrote: >> Methods can be used outside their class, say within another class, only be instantiating a "helper" instance of the method's class. That's a clumsy pattern. > This isn't quite as true as you might think. You can reuse them - in other classes - by direct assignment: Interesting. It's a pattern I haven't used yet. > Where you can get into trouble is when class A's init code causes conflicts with class B. So you have to be thoughtful about initialization. I'd rather just instantiate a helper class ;-) Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/CAMF8tS0xPenB33xahL6S%2B0f6pLqgy%3D7Asyu%2BfghK-1KHggFTFw%40mail.gmail.com.
Re: Using Vitalije's code patterns
On Thursday, January 30, 2020 at 12:10:50 AM UTC-5, Thomas Passin wrote: > > > Class B: > func2(self, parms) = A.func1 > Oops, I meant to write Class B: func2 = A.func1 -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/9216db20-962c-43ac-9191-406bf448bb86%40googlegroups.com.
Re: Using Vitalije's code patterns
On Tuesday, January 7, 2020 at 7:58:41 AM UTC-5, Edward K. Ream wrote: > > While working on leoAst.py, I have come to understand more fully several > of Vitalije's suggested code patterns: > > *Prefer functions to classes/methods* > > Classes and methods are essential in python. They aren't going away. > However, in some cases functions are preferable to methods, for several > reasons: > > 1. Functions are available "everywhere". In contrast, methods are > available only within their enclosing class. > > Methods can be used outside their class, say within another class, only be > instantiating a "helper" instance of the method's class. That's a clumsy > pattern. > > This isn't quite as true as you might think. You can reuse them - in other classes - by direct assignment: Class A: def func1(self, parms): # Do something here Class B: func2(self, parms) = A.func1 # or def func2(self, parms): return A.func1(self, parms) Where you can get into trouble is when class A's init code causes conflicts with class B. So you have to be thoughtful about initialization. Basically, there isn't a lot of difference between a function and a method. It's the difference between result = self.method1(parms) and result = function1(instance, parms) A class method is helpful when the function is closely tied to how the class works, or needs to use a lot of its state. A function is more helpful when it isn't tied so closely to a particular class, or doesn't need to use much of its state. We are fortunate with Python because we can have both, unlike say Java. -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/bd1e5ff2-2a5c-490d-8498-17adf86dcc46%40googlegroups.com.
Re: Using Vitalije's code patterns
Thu, Jan 9, 2020 at 6:58 AM Brian Theado wrote: > I'm guessing this is a response only to my 2nd sentence and not both sentences? Correct. But in this case the present code is better, imo. I'm not suggesting that we should prefer functions to classes generally. Without a class, you would have to implement visit as a callback. Isn't the purpose of 'visit' to be able to loop over the nodes? > The visit method visits the given node. It's natural and good to have subclasses visit nodes in subclass-specific ways. At one extreme, the Fstringify class only cares about BinOp nodes, so Fstringify.visit contains a single test. At the other extreme, other classes could dispatch on the type of node, as is done in Orange.beautify. However, the Orange class doesn't need TOT.traverse, because tokens already are in a specific order. As a result, the Orange class isn't a subclass of TOT. I'm happy with the TOT.traverse where it is. You have little chance of changing my mind. And my mind is elsewhere, as I'll soon explain in a new post about using parse tree data in the Orange class. Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/CAMF8tS1sbpHdN-VbE4ZaOMq6HTeN2CS_Dut_QLO081STSX8TwA%40mail.gmail.com.
Re: Using Vitalije's code patterns
On Thu, Jan 9, 2020 at 5:28 AM Edward K. Ream wrote: > On Wed, Jan 8, 2020 at 10:49 PM Brian Theado > wrote: > > *>> Prefer functions to classes/methods* > > > The TokenOrderTraverser class looks to me like a good opportunity to > follow the above principle. AFAICT, the way it is written, that class is > ONLY useful if it is subclassed. > > True. > I'm guessing this is a response only to my 2nd sentence and not both sentences? > > > For me, subclassing is usually extra friction and the resulting code is > less clear. > > Without a class, you would have to implement visit as a callback. > Isn't the purpose of 'visit' to be able to loop over the nodes? Sounds like the job of a for loop to me. No callbacks and no classes needed. Having the traverse functionality reside in a method of TOT forces the user to subclass. Extracting it into a separate function like traverse_in_token_order allows the user to choose to use a for loop instead. The TOT class can still exist. It would call the same traverse_in_token_order convenience function. If the user want to do the extra work of subclassing TOT, they still can. Brian -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/CAO5X8CyfcQRWX7yPHWXaSY-tdJ%3DxRhtWH_7qZyJfvm1XcJYMZA%40mail.gmail.com.
Re: Using Vitalije's code patterns
On Wed, Jan 8, 2020 at 10:49 PM Brian Theado wrote: *>> Prefer functions to classes/methods* > The TokenOrderTraverser class looks to me like a good opportunity to follow the above principle. AFAICT, the way it is written, that class is ONLY useful if it is subclassed. True. > For me, subclassing is usually extra friction and the resulting code is less clear. Without a class, you would have to implement visit as a callback. Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/CAMF8tS1hJKysk2-aRpgLxMZHVA_VUHBCXy3Lwq%3DoT2pFFjCqPA%40mail.gmail.com.
Re: Using Vitalije's code patterns
On Tue, Jan 7, 2020 at 7:58 AM Edward K. Ream wrote: > While working on leoAst.py, I have come to understand more fully several > of Vitalije's suggested code patterns: > > *Prefer functions to classes/methods* > The TokenOrderTraverser class looks to me like a good opportunity to follow the above principle. AFAICT, the way it is written, that class is ONLY useful if it is subclassed. For me, subclassing is usually extra friction and the resulting code is less clear. If the TokenOrderTraverser.traverse method were written as a function (say 'traverse_in_token_order(tree)') which is exactly the same except in place of calling self.visit(node), it will 'yield node'. Then if you really think you still need to have the TokenOrderTraverser class, you could still implement then the traverse method: def traverse(self, tree): for node in traverse_in_token_order(tree): self.visit(node) IMO, the fstringify code would be clearer if it were not written as a subclass of TOT. With the subclass way, this is the minimum I could imagine to print all the nodes: class TokenOrderPrinter(TokenOrderTraverser): def print(tree): self.traverse(tree) def visit(node): print(str(node)) TokenOrderPrinter().print(tree) The function/generator way has so much less friction for the developer using it: for node in traverse_in_token_order(tree): print(str(node)) Brian -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/CAO5X8CzULeNHG5NnfmtqhiBdNz34LWJg4yJOEBOBR_nDx8_7cA%40mail.gmail.com.
Using Vitalije's code patterns
While working on leoAst.py, I have come to understand more fully several of Vitalije's suggested code patterns: *Prefer functions to classes/methods* Classes and methods are essential in python. They aren't going away. However, in some cases functions are preferable to methods, for several reasons: 1. Functions are available "everywhere". In contrast, methods are available only within their enclosing class. Methods can be used outside their class, say within another class, only be instantiating a "helper" instance of the method's class. That's a clumsy pattern. 2. Functions help "disentangle" classes. This is a direct consequence of point 1. Code shared via functions reduces dependencies between classes. Disentangling classes greatly simplified the code in leoAst.py. *Prefer limited duplication of code* I have come to see that there is an ongoing, never-to-be-fully-resolved, tension between the DRY (Don't repeat yourself) principle and other design principles. In particular, *limited* duplication of code can help untangle code. The great Glenford Myers talked about avoiding "modules" whose only purpose was to avoid duplicating code. I should have paid more attention. I have come to see that some code duplication can sometimes be seen as documentation. The fs.fstringify_file and fs.fstringify_file_diff methods both contain the following code: tog = TokenOrderGenerator() contents, tokens, tree = tog.init_from_file(filename) if not contents or not tokens or not tree: return False # fstringify. self.fstringify(contents, filename, tokens, tree) results = tokens_to_string(tokens) Imo, this duplicated code has no series negative consequences. *Avoid kwargs* This has been an ongoing project. I had overused kwargs in order to "share" code. This often has significant negative consequences. Better to keep functions and methods simple, and accept a bit of code duplication. *Summary* Functions can sometimes preferable to methods. They are more easily accessible and they may disentangle the relationships between classes. Limited code duplication can also be useful. In some cases, they serve as useful documentation. Avoiding kwargs is often a good idea, despite the potential for code duplication. I thank Vitalije for his helpful suggestions. These ideas would not have come to me on my own. The code in leoAst.py is an example of my revised coding style. Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/leo-editor/7de4afbe-373e-452b-89e1-e448cba2f81b%40googlegroups.com.