Re: Pygobject style question
On 01Aug2020 13:32, Chris Green wrote: >Having (after lots of help from here, thank you) finally converted my >Python 2, gtk 2 program to Python 3 and pygobject gtk 3 I'm left with >a couple of what might be called style questions. > >I guess it's mostly down to what feels right to me but there may be >good reasons for choosing one way over another and, if so, I'd like to >know what they are. > >So, my original code had:- >... >self.buffer = gtk.TextBuffer() >self.view = gtk.TextView(self.buffer) > >This doesn't work in gtk+ 3 (or at least I don't think it does, the >converter script changed it) and there seem to be several ways of >doing it now:- > >self.buffer = Gtk.TextBuffer() >self.view = Gtk.TextView(buffer = self.buffer) I like this first one. It is least verbose, and it makes the buffer before it makes the view, which I prefer. If they are all legal and all correct and equivalent, go with the one which is easiest to read. Cheers, Cameron Simpson -- https://mail.python.org/mailman/listinfo/python-list
Re: Package setup best practice style question
On Sun, 29 May 2016 03:00 am, Steven D'Aprano wrote: > On Sun, 29 May 2016 02:15 am, Gerald Britton wrote: > >> suppose I have a simple python project setup like this: [...] To which I responded: > If this is a single project, why do you set it up like this? Is there a > reason why you don't just have: [...] I'm sorry, on re-reading my post I realise that it might come across as a bit confrontational. Sorry Gerald, it wasn't intended that way. I was just intending to point out that we aren't forced to use a package structure at all, unless it brings actual advantages to the project. -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Package setup best practice style question
On Sun, 29 May 2016 02:15 am, Gerald Britton wrote: > suppose I have a simple python project setup like this: > > Project diectory > prog.py > pkg directory > __init__.py > mod1.py >class A: If this is a single project, why do you set it up like this? Is there a reason why you don't just have: prog.py # contains class A or even: prog.py mod1.py # contains class A Or if the project is so big it needs to be a package, make it executable: prog/ __init__.py mod1.py __main__.py This layout is now executable using: python -m prog which automatically calls __main__.py. But if you don't have a good reason for using a package, don't use a package. Use the simplest project layout that solves your problem. But for the rest of my comments, I'm going to assume that you DO have a good reason. > In order to have class A (unqualified) available from prog.py, there are a > few options that I know about. I'm currently considering two of them and > would like some feedback on best practices. > > 1. in pkg.__init__.py add: > >from pkg.mod1 import A This kinda-sorta defeats the purpose, or at least one purpose, of using a package. Which is fine, so long as you understand that's what you are doing. Generally speaking, one of the purposes of using a package layout is to allow unused sub-modules to be left unloaded unless needed. So pkg.mod1 doesn't get loaded unless you need it, in which case you explicitly call import pkg.mod1 or from pkg.mod1 import A as you prefer. By putting that import in the pkg __init__ file, you're making it automatically occur as soon as pkg is imported. Is that what you intend? If so, then it is fine, and feel free to do it. But in that case, why not just move class A into pkg/__init__.py? > in prog.py add: > >from pkg import A *shrug* This entirely depends on the purpose and use of pkg. When you give generic, meaningless names, I can only respond with wishy-washy, sit-on- the-fence generic advice. If the appropriate API is for callers to say: from pkg import A then this is the right way to design your package. But if the right API is: from pkg.mod1 import A then don't do it this way, instead do it as follows. > 2. leave __init__.py empty > in prog.py add: > > from pkg.mod1 import A > > > Is there a preference or best practice that would indicate to prefer > method > 1 or method 2? Are there methods 3, 4, 5, ... that I should consider that > are even better? One purpose of using a package is to have alternative implementations. For instance I have a package which has to support Python 2.4 where the "with" statement is not available, so I design it like this: package/ __init__.py module.py module24.py Since the user doesn't choose which implementation to use, I have this in the init file: try: from module import thing except SyntaxError: from module24 import thing and then the caller uses: from package import thing and is none the wiser. On the other hand, if the user was supposed to choose, then I would have then call: from package.redblack import Tree from package.avl import Tree from package.scapegoat import Tree and let the user choose which implementation they wanted. -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Package setup best practice style question
suppose I have a simple python project setup like this: Project diectory prog.py pkg directory __init__.py mod1.py class A: In order to have class A (unqualified) available from prog.py, there are a few options that I know about. I'm currently considering two of them and would like some feedback on best practices. 1. in pkg.__init__.py add: from pkg.mod1 import A in prog.py add: from pkg import A 2. leave __init__.py empty in prog.py add: from pkg.mod1 import A Is there a preference or best practice that would indicate to prefer method 1 or method 2? Are there methods 3, 4, 5, ... that I should consider that are even better? -- Gerald Britton, MCSE-DP, MVP LinkedIn Profile: http://ca.linkedin.com/in/geraldbritton -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
On Thursday, October 30, 2014 4:10:23 AM UTC-7, Steven D'Aprano wrote: I don't particularly like either version. I prefer this: def load_int(obj): if isinstance(obj, int): # Case 1), an int, e.g. 7 return obj elif isinstance(obj, str): # Case 2) and 3), a str or JSON serialised int. # E.g. '7' or '7'. try: return int(obj) except ValueError: return int(json.loads(obj)) raise TypeError('require int or str, got %s' % type(obj).__name__) This will definitely work, but then I don't see a benefit of EAFP and duck-typing: Let's say I have a class class FakeInt(object): def __int__(self): return 42 In this case: fi = FakeInt() isinstance(fi, int) False int(fi) 42 So probably I need to rephrase 1) something, that I can cast to int. Same for elif isinstance(obj, str): As long as it behaves like string (can be some sort if bytearray). For particularly this case, it will probably won't happen, but again, it looks like an overloaded function with strongly typed argument. or a functional form: def tolerant_load_int(obj, default=None): try: return load_int(obj) except (ValueError, TypeError): return default values = [n for n in map(tolerant_load_int, l) if n is not None] # alternative to using map values = [n for n in (tolerant_load_int(obj) for obj in l) if n is not None] I like the idea of wrapping it up in a function and being able to use it in these functional forms. -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. I don't particularly like either version. I prefer this: def load_int(obj): if isinstance(obj, int): # Case 1), an int, e.g. 7 return obj elif isinstance(obj, str): # Case 2) and 3), a str or JSON serialised int. # E.g. '7' or '7'. try: return int(obj) except ValueError: return int(json.loads(obj)) raise TypeError('require int or str, got %s' % type(obj).__name__) load_int() covers the three cases you mention, and raises either ValueError for malformed strings (e.g. 'x') or TypeError for things which aren't ints (e.g. floats, dicts, etc.). Any other exception is probably a bug that needs to be fixed. Then, to cover case 4), ignoring everything else, you have a choice between a procedural form: values = [] for obj in l: try: values.append(load_int(obj)) except (ValueError, TypeError): pass or a functional form: def tolerant_load_int(obj, default=None): try: return load_int(obj) except (ValueError, TypeError): return default values = [n for n in map(tolerant_load_int, l) if n is not None] # alternative to using map values = [n for n in (tolerant_load_int(obj) for obj in l) if n is not None] -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
On 2014-10-30 11:10, Steven D'Aprano wrote: Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. I don't particularly like either version. I prefer this: def load_int(obj): if isinstance(obj, int): # Case 1), an int, e.g. 7 return obj elif isinstance(obj, str): # Case 2) and 3), a str or JSON serialised int. # E.g. '7' or '7'. try: return int(obj) except ValueError: return int(json.loads(obj)) raise TypeError('require int or str, got %s' % type(obj).__name__) [snip] How about: int(str(obj).strip('')) -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
MRAB wrote: On 2014-10-30 11:10, Steven D'Aprano wrote: Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. I don't particularly like either version. I prefer this: def load_int(obj): if isinstance(obj, int): # Case 1), an int, e.g. 7 return obj elif isinstance(obj, str): # Case 2) and 3), a str or JSON serialised int. # E.g. '7' or '7'. try: return int(obj) except ValueError: return int(json.loads(obj)) raise TypeError('require int or str, got %s' % type(obj).__name__) [snip] How about: int(str(obj).strip('')) Absolutely not. obj = '1\n\n\n\n' # not valid JSON load_int(obj) = raises ValueError int(str(obj).strip('')) = wrongly returns 1 -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
In article 54521c8f$0$12982$c3e8da3$54964...@news.astraweb.com, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. I don't particularly like either version. I prefer this: def load_int(obj): if isinstance(obj, int): # Case 1), an int, e.g. 7 return obj elif isinstance(obj, str): # Case 2) and 3), a str or JSON serialised int. # E.g. '7' or '7'. try: return int(obj) except ValueError: return int(json.loads(obj)) raise TypeError('require int or str, got %s' % type(obj).__name__) Depending on how strictly you're trying to do input validation, the int(json.loads(obj)) may not be what you want. It allows well-formed json encoding floats, for example. And, of course, since isinstance(True, int) True this code accepts booleans. Oh, but wait, that's by design :-) -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
Roy Smith wrote: In article 54521c8f$0$12982$c3e8da3$54964...@news.astraweb.com, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. I don't particularly like either version. I prefer this: def load_int(obj): if isinstance(obj, int): # Case 1), an int, e.g. 7 return obj elif isinstance(obj, str): # Case 2) and 3), a str or JSON serialised int. # E.g. '7' or '7'. try: return int(obj) except ValueError: return int(json.loads(obj)) raise TypeError('require int or str, got %s' % type(obj).__name__) Depending on how strictly you're trying to do input validation, the int(json.loads(obj)) may not be what you want. It allows well-formed json encoding floats, for example. Really? py int(json.loads(json.dumps(23.5))) 23 Damn! You're right. Back to Plan A: elif isinstance(obj, str): try: return int(obj) except ValueError: if obj and obj.startswith('') and obj.endswith(''): return int(obj[1:-1]) raise But of course even the int() function itself may be a little more flexible than we might want: py int('1') 1 So I guess the lessons are: * before writing code, you need to decide what the code is meant to do; * and that includes what input must be rejected, not just what input must be accepted. And, of course, since isinstance(True, int) True this code accepts booleans. Oh, but wait, that's by design :-) Naturally :-) If you wanted to avoid it, that's easy, add a clause: if isinstance(obj, bool): raise TypeError at the start of the function. -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
On Fri, 31 Oct 2014 09:48:10 +1100, Steven D'Aprano wrote: MRAB wrote: How about: int(str(obj).strip('')) Absolutely not. obj = '1\n\n\n\n' # not valid JSON load_int(obj) = raises ValueError int(str(obj).strip('')) = wrongly returns 1 How about #!/usr/bin/python import re, json l = [1, -1, 0, '+2', '2', '-2', '0', '+3', '3', '-3', '0', json.dumps(-4), json.dumps(4), json.dumps(0), 'x', 'sqjklsqjk__', (5, 6), 7.7, -7.7, '8.8', '+8.8', '-8.8', '9.9', '+9.9', '-9.9'] patt1 = re.compile(r'^([-+]?\d+)$') patt2 = re.compile(r'^([-+]?\d+)$') def getTheInt(x): if isinstance(x,int): return x if isinstance(x,str): tmp = patt1.match(x) if tmp: return int(tmp.group(1)) tmp = patt2.match(x) if tmp: return int(tmp.group(1)) return None a = [] for n in l: a.append(getTheInt(n)) print a # end of code prints: [1, -1, 0, 2, 2, -2, 0, 3, 3, -3, 0, -4, 4, 0, None, None, None, None, None, None, None, None, None, None, None] I know re matching the strings may be overkill, but it may be the best way of checking that the string contains the expected character format to convert to an int. -- Denis McMahon, denismfmcma...@gmail.com -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 29/10/2014 10:45, Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. Variant 1 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: pass else: values.add(c_int) continue # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue === Is this code ugly? Does it follow EAFP? Am I missing something in language best practice? Or maybe below is more preferable way with a nested try...except clause? Variant 2 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue else: values.add(c_int) continue === Thanks, Anton. Your first example is perfectly fine and is EAFP Personally, I prefer to avoid nesting when it's not necessary. - -- Martin Kemp (martin.k...@ingg.com) -BEGIN PGP SIGNATURE- Version: GnuPG v2 iQEcBAEBAgAGBQJUUM7zAAoJEJ0Re0UIDzSucugIALn/zY8RdpP8iaMShHoszzqf I0zl0mFHyqhNtwgQ0ZF7VGO+H+U0Dk8rhzTYOmEMzPTKNBGwll3fda9mOnrK9Xvp 9gQjII6DyQIWH7Z3dLcLr2e1j8OMNUSL6UmAYs8urNSIKZLowdV3JI4G/bLyW0KS y5Ko8dI6y5nOJ1P9XCmPTmags43UZfR8DrBUaAbzNcS8FGwmUE2KBkEhLQOvmpJi jmMc7wMOpq0jL+XbA+7pHUqoVZ7w1tUFjuy9I3h45tgPuTFAFB0gX+FpE+oVgO5o spQpVaOPEYN9ceLgHdKSxzdVIhOQLE6H/SYNHlsEW/ZNM6aR9n4yipgkOmtJ0+M= =WzHA -END PGP SIGNATURE- -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
Hi, first in Python 2.7.6 and Python 3.4.0 list haven't got any add function but they have append. I think you could do better with something like == import json l = [1, -1, 0, '1', '-1', '0', json.dumps(-1), json.dumps(1), json.dumps(0), 'x', 'sqjklsqjk__', (1, 2)] values = [] for c in l: try: c_int = int(c) except ValueError: pass except TypeError: pass else: values.append(c_int) continue print(values) == The code has been tested in Python 2.7.6 and 3.4 and returns [1, -1, 0, 1, -1, 0, -1, 1, 0] You don't need to do two try because you can process both exceptions in the same way. You don't really need to do json.loads because if you have a json string which is an integer, you could do that directly with int(c) which can take a string and transform in an integer. With ValueError it captures the exception when it tries to transform the characters' strings and with TypeError it captures the exception when it tries to work with the tuples. Have a good day and hope it works for you! 2014-10-29 11:42 GMT+01:00 Anton anton.schattenf...@gmail.com: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. Variant 1 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: pass else: values.add(c_int) continue # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue === Is this code ugly? Does it follow EAFP? Am I missing something in language best practice? Or maybe below is more preferable way with a nested try...except clause? Variant 2 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue else: values.add(c_int) continue === Thanks, Anton. -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
2014-10-29 12:25 GMT+01:00 Martin Kemp martin.k...@ingg.com: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 29/10/2014 10:45, Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. Variant 1 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: pass else: values.add(c_int) continue # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue === Is this code ugly? Does it follow EAFP? Am I missing something in language best practice? Or maybe below is more preferable way with a nested try...except clause? Variant 2 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue else: values.add(c_int) continue === Thanks, Anton. Your first example is perfectly fine and is EAFP Actually it doesn't work because there is no add function and it doesn't catch the TypeError function to ignore other exceptions than ValueError. Doesn't it? I tested in Python 2.7.6 and 3.4. Personally, I prefer to avoid nesting when it's not necessary. - -- Martin Kemp (martin.k...@ingg.com) -BEGIN PGP SIGNATURE- Version: GnuPG v2 iQEcBAEBAgAGBQJUUM7zAAoJEJ0Re0UIDzSucugIALn/zY8RdpP8iaMShHoszzqf I0zl0mFHyqhNtwgQ0ZF7VGO+H+U0Dk8rhzTYOmEMzPTKNBGwll3fda9mOnrK9Xvp 9gQjII6DyQIWH7Z3dLcLr2e1j8OMNUSL6UmAYs8urNSIKZLowdV3JI4G/bLyW0KS y5Ko8dI6y5nOJ1P9XCmPTmags43UZfR8DrBUaAbzNcS8FGwmUE2KBkEhLQOvmpJi jmMc7wMOpq0jL+XbA+7pHUqoVZ7w1tUFjuy9I3h45tgPuTFAFB0gX+FpE+oVgO5o spQpVaOPEYN9ceLgHdKSxzdVIhOQLE6H/SYNHlsEW/ZNM6aR9n4yipgkOmtJ0+M= =WzHA -END PGP SIGNATURE- -- https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 29/10/2014 12:01, Rafael Romero Carmona wrote: 2014-10-29 12:25 GMT+01:00 Martin Kemp martin.k...@ingg.com: On 29/10/2014 10:45, Anton wrote: Let's say I have an incoming list of values *l*. Every element of *l* can be one of the following options: 1) an integer value 2) a string in form of 'int_value', e.g. '7' 3) a string with a json serialization of an integer value, e.g. '7' 4) something else that should be ignored I need to transform this list into another list with values from options 1)-3) coerced to int. The code below should do this. Variant 1 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: pass else: values.add(c_int) continue # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue === Is this code ugly? Does it follow EAFP? Am I missing something in language best practice? Or maybe below is more preferable way with a nested try...except clause? Variant 2 === values = [] for c in l: # Case 1) or 2) try: c_int = int(c) except ValueError: # Case 3) try: c_int = int(json.loads(c)) except ValueError: pass else: values.add(c_int) continue else: values.add(c_int) continue === Thanks, Anton. Your first example is perfectly fine and is EAFP Actually it doesn't work because there is no add function and it doesn't catch the TypeError function to ignore other exceptions than ValueError. Doesn't it? I tested in Python 2.7.6 and 3.4. Personally, I prefer to avoid nesting when it's not necessary. -- https://mail.python.org/mailman/listinfo/python-list Ah ok, style-wise it was fine. - -- Martin Kemp (martin.k...@ingg.com) -BEGIN PGP SIGNATURE- Version: GnuPG v2 iQEcBAEBAgAGBQJUUOD+AAoJEJ0Re0UIDzSu1KQIAK6aCMOv4VqOjmm/zoQrmzLf UGBCLwtHrnDkbXFAIweTSFiM1uf9TDaRpJqY1IrPbJHI4/EAP0Hu07nyx3V6HgzM /+Wb3DkpjW+JQoVqDSGzE/dTPJcU3/b1/EWWpbu72JHplqz9laEAFt9muWyDPs9u kDgM06mDd50lsi83W3i0H1iGL6YbLtsik+/x4G4mMjdq1o9BvRpUjkIiOx7yJ/BR OYzdudltXGqlXcToufHTU2lUv2C0RoHHNO4kytiLoUekCBdGE+Jy/6gQq/AKQu4G 0RYjCOnKNgugfdmDuHi0julPtTEzc+MdY/CcPob4cyy8RDzfQGklGKHP7f9+SJs= =hjWU -END PGP SIGNATURE- -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
On Wednesday, October 29, 2014 4:43:33 AM UTC-7, Rafael Romero Carmona wrote: Hi, first in Python 2.7.6 and Python 3.4.0 list haven't got any add function but they have append. You are right, in my original code I use set instead of array, so it should be either values = set() or values.append() in the original code. I think you could do better with something like == import json l = [1, -1, 0, '1', '-1', '0', json.dumps(-1), json.dumps(1), json.dumps(0), 'x', 'sqjklsqjk__', (1, 2)] It should also work with cases like [1, json.dumps('-1')], which is case 3), sorry if it was not clear in the initial post. values = [] for c in l: try: c_int = int(c) except ValueError: pass except TypeError: pass else: values.append(c_int) continue print(values) == The code has been tested in Python 2.7.6 and 3.4 and returns [1, -1, 0, 1, -1, 0, -1, 1, 0] You don't need to do two try because you can process both exceptions in the same way. You don't really need to do json.loads because if you have a json string which is an integer, you could do that directly with int(c) which can take a string and transform in an integer. In case of 3) an element can be a string like '1', which will fail int(...), in this case it tries to parse it with json. -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
On Wednesday, October 29, 2014 4:59:25 AM UTC-7, Rafael Romero Carmona wrote: 2014-10-29 12:25 GMT+01:00 Martin Kemp mar...@ingg.com: Actually it doesn't work because there is no add function and it doesn't catch the TypeError function to ignore other exceptions than ValueError. Doesn't it? I tested in Python 2.7.6 and 3.4. Originally I was using set instead of list. So it should have been either values = set() or values.append(), but it is not relevant to the question. Regarding TypeError, I don't catch it on purpose, because I want this type of Exception to bubble up and surface as an error and be logged, because this should never be the case. I expect an element to be either something coercible to int or a string. If for some reason it is an object, then there is something wrong one layer up, so I want it to fail explicitly. -- https://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
I'd bet you would stress your point Steven! But you don't need to persuade me, I do already agree. I just meant to say that, when the advantage is little, there's no need to rewrite a working function. And that with modern CPUs, if tests take so little time, that even some redundant one is not so much of a nuisance. in your working example, the payload is just a couple of integer calculations, that take very little time too. So the overhead due to redundant if tests does show clearly. And also in that not-really-real situation, 60% overhead just meant less than 3 seconds. Just for the sake of discussion, I tried to give both functions some plough to pull, and a worst-case situation too: t1 = Timer('for x in range(100): print func1(0),', ... 'from __main__ import func1') t2 = Timer('for x in range(100): print func2(0),', ... 'from __main__ import func2') min(t1.repeat(number=1, repeat=1)) -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 53.011015366479114 min(t2.repeat(number=1, repeat=1)) -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 47.55442856564332 that accounts for a scant 11% overhead, on more than one million tests per cycle. That said, let's make really clear that I would heartily prefer func2 to func1, based both on readability and speed. Thank you for having spent some time playing with me! Francesco On 19/12/2010 1.05, Steven D'Aprano wrote: Well, let's try it with a working (albeit contrived) example. This is just an example -- obviously I wouldn't write the function like this in real life, I'd use a while loop, but to illustrate the issue it will do. def func1(n): result = -1 done = False n = (n+1)//2 if n%2 == 1: result = n done = True if not done: n = (n+1)//2 if n%2 == 1: result = n done = True if not done: n = (n+1)//2 if n%2 == 1: result = n done = True if not done: for i in range(100): if not done: n = (n+1)//2 if n%2 == 1: result = n done = True return result def func2(n): n = (n+1)//2 if n%2 == 1: return n n = (n+1)//2 if n%2 == 1: return n n = (n+1)//2 if n%2 == 1: return n for i in range(100): n = (n+1)//2 if n%2 == 1: return n return -1 Not only is the second far more readable that the first, but it's also significantly faster: from timeit import Timer t1 = Timer('for i in range(20): x = func1(i)', ... 'from __main__ import func1') t2 = Timer('for i in range(20): x = func2(i)', ... 'from __main__ import func2') min(t1.repeat(number=10, repeat=5)) 7.3219029903411865 min(t2.repeat(number=10, repeat=5)) 4.530779838562012 The first function does approximately 60% more work than the first, all of it unnecessary overhead. -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Sat, 18 Dec 2010 19:59:45 -0800, Carl Banks wrote: On Dec 17, 12:23 am, Steven D'Aprano steve +comp.lang.pyt...@pearwood.info wrote: On Thu, 16 Dec 2010 20:32:29 -0800, Carl Banks wrote: Even without the cleanup issue, sometimes you want to edit a function to affect all return values somehow. If you have a single exit point you just make the change there; if you have mulitple you have to hunt them down and change all of them--if you remember to. I just got bit by that one. If your function has so many exit points that you can miss some of them while editing, your function is too big, does too much, or both. Sanctimonious much? In the real world, people miss things and make mistakes and not necessarily because they are working on something too complex to handle. It happens. Really? I had no idea. I've never made a misteak, I asumed evrybody else was equally brilliant. No, wait, there was that one time... *wink* Of course people make mistakes. So what's your point? The point I was trying to make is that rather than encouraging an idiom (only one return statement, even if the algorithm is more clearly written with multiple exists) that leads to more complex, less efficient code just in case you might someday need to modify the return result, there are simple alternatives that avoid the need for anti-patterns like copy- and-paste coding or enforced single exit point. I gave two: - refactor the complex code so that it's less complex (e.g. instead of 20 exit points, which makes it easy to miss one or two, refactor it so there are two or three exit points); or if that's not practical: - wrap it in a decorator that performs the post-processing you need. Both can be simple, effective and Pythonic. Neither require the coder to use an artificial idiom just in case of some future need. The decorator solution works even if you don't have access to the source code, or if the function is a complex black box that nobody understands well enough to touch. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 17/12/2010 0.51, Steven D'Aprano wrote: Don't get me wrong... spaghetti code is*bad*. But there are other ways of writing bad code too, and hanging around inside a function long after you've finished is also bad: def function(arg): done = False do_something() if some_condition: result = finished done = True if not done: do_something_else() if another_condition: result = now we're finished done = True if not done: do_yet_more_work() if third_condition: result = finished this time for sure done = True if not done: for i in range(100): if not done: do_something_small() if yet_another_condition: result = finally done! done = True return result It's far more complicated than it need be, and does*lots* of unnecessary work. This can be written more simply and efficiently as: def function(arg): do_something() if some_condition: return finished do_something_else() if another_condition: return now we're finished do_yet_more_work() if third_condition: return finished this time for sure for i in range(100): do_something_small() if yet_another_condition: return finally done! I agree to your point, but I'm afraid you chose a wrong example (AFAIK, and that's not much). Sure, the second version of function(arg) is much more readable, but why do you think the first one would do *lots* of unnecessary work? All the overhead in that function would be: if some_condition, three IF tests, and you know that's NOT a lot! if no conditions were met, (worst case) the first version would return an exception (unless result was globally defined) while the second would happily return None. Apart from this, the overhead in the first one would amount to one million IF tests, again not a lot these days. I don't think I would rewrite that function, if I found it written in the first way... I don't mean that the fist example is better, just I'm sure you could imagine a more compelling proof of your concept. Maybe there's something I don't know... in that case, please enlighten me! Francesco -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Sat, 18 Dec 2010 12:29:31 +0100, Francesco wrote: [...] I agree to your point, but I'm afraid you chose a wrong example (AFAIK, and that's not much). Sure, the second version of function(arg) is much more readable, but why do you think the first one would do *lots* of unnecessary work? All the overhead in that function would be: if some_condition, three IF tests, and you know that's NOT a lot! Well, let's try it with a working (albeit contrived) example. This is just an example -- obviously I wouldn't write the function like this in real life, I'd use a while loop, but to illustrate the issue it will do. def func1(n): result = -1 done = False n = (n+1)//2 if n%2 == 1: result = n done = True if not done: n = (n+1)//2 if n%2 == 1: result = n done = True if not done: n = (n+1)//2 if n%2 == 1: result = n done = True if not done: for i in range(100): if not done: n = (n+1)//2 if n%2 == 1: result = n done = True return result def func2(n): n = (n+1)//2 if n%2 == 1: return n n = (n+1)//2 if n%2 == 1: return n n = (n+1)//2 if n%2 == 1: return n for i in range(100): n = (n+1)//2 if n%2 == 1: return n return -1 Not only is the second far more readable that the first, but it's also significantly faster: from timeit import Timer t1 = Timer('for i in range(20): x = func1(i)', ... 'from __main__ import func1') t2 = Timer('for i in range(20): x = func2(i)', ... 'from __main__ import func2') min(t1.repeat(number=10, repeat=5)) 7.3219029903411865 min(t2.repeat(number=10, repeat=5)) 4.530779838562012 The first function does approximately 60% more work than the first, all of it unnecessary overhead. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Dec 17, 12:23 am, Steven D'Aprano steve +comp.lang.pyt...@pearwood.info wrote: On Thu, 16 Dec 2010 20:32:29 -0800, Carl Banks wrote: Even without the cleanup issue, sometimes you want to edit a function to affect all return values somehow. If you have a single exit point you just make the change there; if you have mulitple you have to hunt them down and change all of them--if you remember to. I just got bit by that one. If your function has so many exit points that you can miss some of them while editing, your function is too big, does too much, or both. Sanctimonious much? In the real world, people miss things and make mistakes and not necessarily because they are working on something too complex to handle. It happens. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Thu, 16 Dec 2010 20:32:29 -0800, Carl Banks wrote: Even without the cleanup issue, sometimes you want to edit a function to affect all return values somehow. If you have a single exit point you just make the change there; if you have mulitple you have to hunt them down and change all of them--if you remember to. I just got bit by that one. If your function has so many exit points that you can miss some of them while editing, your function is too big, does too much, or both. Refactor and simplify. Or wrap the function in a decorator: def affect_all_return_values(func): @functools.wraps(func) def inner(*args, **kwargs): result = func(*args, **kwargs) do_something_to(result) return result return inner @affect_all_return_values def my_big_complicated_function(args): do_something_with_many_exit_points() -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? Thanks. What about, def myMethod(): for condition, exitCode in [ (cond1, 'error1'), (cond2, 'very bad error'), ]: if not condition: break else: do_some_usefull_stuff() # executed only if the we never hit the break statement. exitCode = good1 return exitCode This version uses the 'for ... else' statement. You can easily add conditions by simply adding a line in the list, that's it. Note that this code uses a shadow declaration of exitCode in the for loop. If you're not comfortable with that, you'll have to use a properly 'declared' variable retCode and write retCode = exitCode before breaking. Actually I would advise to do so. JM -- http://mail.python.org/mailman/listinfo/python-list
RE: If/then style question
-Original Message- What about, def myMethod(): for condition, exitCode in [ (cond1, 'error1'), (cond2, 'very bad error'), ]: if not condition: break else: do_some_usefull_stuff() # executed only if the we never hit the break statement. exitCode = good1 return exitCode I reply - This is interesting, but I don't understand it (which speaks volumes about the level of my understanding of Python). First, just to clarify, I don't think the indentation I saw was what was originally posted. The else must be indented to match the if, and the two statements under else are in the else block. The return statement is indented at the same level as the for statement, so that it will be executed after the for loop exits. Correct? Now, the for loop will set condition to cond1 and exitCode to 'error1'. Then it checks the contents of the condition variable. But what does not variable_name by itself mean? I'm guessing that it checks that the variable refers to an object. So, the first time through, condition refers to cond1, the if condition is false, and the else block gets executed, and exitCode is changed to refer to good1. The next time through the loop, condition is set to refer to cond2 and exitCode is set to refer to 'very bad error'. Again, condition is refering to something, so the else block is executed and we do useful stuff again, which is probably not helpful and could well be harmful. exitCode is set to good1, we're finished with the loop, and we return exitCode. What happens if we try to do useful stuff, and we can't? Where does the error indication get set? And once it does get set, the only way we can exit the for loop is for condition to not refer to anything. How can that happen? Thank you very much for your explanation and your patience with one who only uses Python in very simplistic ways. RobR -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Fri, 17 Dec 2010 09:09:49 -0500, Rob Richardson wrote: First, just to clarify, I don't think the indentation I saw was what was originally posted. The else must be indented to match the if, and the two statements under else are in the else block. The return statement is indented at the same level as the for statement, so that it will be executed after the for loop exits. Correct? I think that what you are missing is that for-loops can include an else clause too, like this: for x in (1,2,3): ... print(x) ... else: ... print(finished) ... 1 2 3 finished The else block runs after the for block, unless you exit the entire block by returning, raising an exception, or using break: for x in (1,2,3): ... print(x) ... if x == 3: break ... else: ... print(finished) ... 1 2 3 Does that clear up what is going on? -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Rob Richardson wrote: -Original Message- What about, def myMethod(): for condition, exitCode in [ (cond1, 'error1'), (cond2, 'very bad error'), ]: if not condition: break else: do_some_usefull_stuff() # executed only if the we never hit the break statement. exitCode = good1 return exitCode I reply - This is interesting, but I don't understand it (which speaks volumes about the level of my understanding of Python). First, just to clarify, I don't think the indentation I saw was what was originally posted. The else must be indented to match the if, and the two statements under else are in the else block. No, the else is indented to the for loop. for ... else is a python statement, the else block is executed only if the loop did never break. http://docs.python.org/reference/compound_stmts.html#for The return statement is indented at the same level as the for statement, so that it will be executed after the for loop exits. Correct? Now, the for loop will set condition to cond1 and exitCode to 'error1'. Then it checks the contents of the condition variable. But what does not variable_name by itself mean? condition is a bool value. if not condition is evaluated to True, if the condition is False. condition = False not condition = True condition = ('Foo' == 'Foo') not condition = False [snip] RobR My mail client could have messed up with the indentation. Here is the code: http://paste-it.net/public/t8a4acd/python/ JM -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Thu, Dec 16, 2010 at 6:51 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: ... Functions always have one entry. The only way to have multiple entry points is if the language allows you to GOTO into the middle of a function, and Python sensibly does not allow this. The one entry, one exit rule comes from the days when people would routinely write spaghetti code, jumping into and out of blocks of code without using functions at all. Only 99.7% true. Fortran still allows the appalling ENTRY statement. -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 12/17/2010 9:38 AM, Steven D'Aprano wrote: On Fri, 17 Dec 2010 09:09:49 -0500, Rob Richardson wrote: First, just to clarify, I don't think the indentation I saw was what was originally posted. The else must be indented to match the if, and the two statements under else are in the else block. The return statement is indented at the same level as the for statement, so that it will be executed after the for loop exits. Correct? I think that what you are missing is that for-loops can include an else clause too, like this: for x in (1,2,3): ... print(x) ... else: ... print(finished) ... 1 2 3 finished The else block runs after the for block, unless you exit the entire block by returning, raising an exception, or using break: for x in (1,2,3): ... print(x) ... if x == 3: break ... else: ... print(finished) ... 1 2 3 Does that clear up what is going on? This construct appears to be unpopular in actual use, and when it comes up in classes and seminars there is always interesting debate as people discuss potential uses and realise there are useful applications. I think the choice of keyword is probably not Guido's crowning language achievement, but then since the English keywords don't make natural sense to those who speak other languages it's at least fair that there should be one that isn't totally natural to English speakers. A small price to pay for all the other keywords not being Dutch. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 PyCon 2011 Atlanta March 9-17 http://us.pycon.org/ See Python Video! http://python.mirocommunity.org/ Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
RE: If/then style question
My thanks for pointing out the existence of the else: suite in the for statement. However, I remain confused. For reference, here's the original code: def myMethod(): for condition, exitCode in [ (cond1, 'error1'), (cond2, 'very bad error'), ]: if not condition: break else: do_some_usefull_stuff() # executed only if the we never hit the break statement. exitCode = good1 return exitCode What do we know about cond1 and cond2? Do they have to be assigned before this for statement is executed? The sample code doesn't show it. The loop is going to to execute once for condition = cond1 and exitCode = 'error1'. The only thing it's going to do is check to see what condition is. Since we can assume (I hope) that cond1 is not false, then the for loop continues. Now condition = cond2 and exitCode = 'very bad error'. The if condition is still false, so the loop continues. We've come to the end now, and the else: suite is executed. We finally do some useful stuff and exitCode = good1. (Should that have been in quotes, or doesn't it matter?) But now the for loop's job is done and we return the exitCode, which at this point is good1. But I still don't understand what happens if we can't do useful stuff. Where does an error code get set, and where is that error code checked? We don't have a chance to check it in the for loop, because once we're in the else: suite the loop condition is never rechecked. Or is it? Thanks again! RobR -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 17/12/2010 15:53, Steve Holden wrote: [... snip example of for-else ...] This construct appears to be unpopular in actual use, and when it comes up in classes and seminars there is always interesting debate as people discuss potential uses and realise there are useful applications. I use this not infrequently, and I like it when it seems to be an elegant way to express the code path. But I still misremember from time to time and assume that the else clause fires when the for loop is empty. TJG -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Jean-Michel Pichavant jeanmic...@sequans.com writes: What about, def myMethod(): for condition, exitCode in [ (cond1, 'error1'), (cond2, 'very bad error'), ]: if not condition: break else: do_some_usefull_stuff() # executed only if the we never hit the break statement. exitCode = good1 return exitCode This version uses the 'for ... else' statement. For..else always has seemed ugly and confusing to me, as does that thing of using the captured loop indexes after the loop finishes. I'd prefer a more functional style (untested): def myMethod(): def success(): do_some_usefull_stuff() return good1 cond_table = [ (cond1, lambda: 'error1'), (cond2, lambda: 'very bad error'), (True, success) ] func = next(f for c,f in cond_table if c) return func() This uses the next() builtin from Python 2.6. You could make it more concise: def myMethod(): cond_table = [ (cond1, lambda: 'error1'), (cond2, lambda: 'very bad error'), (True, lambda: (do_some_usefull_stuff(), good1)[1]) ] return next(f for c,f in cond_table if c)() -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Rob Richardson wrote: My thanks for pointing out the existence of the else: suite in the for statement. However, I remain confused. For reference, here's the original code: def myMethod(): for condition, exitCode in [ (cond1, 'error1'), (cond2, 'very bad error'), ]: if not condition: break else: do_some_usefull_stuff() # executed only if the we never hit the break statement. exitCode = good1 return exitCode What do we know about cond1 and cond2? Do they have to be assigned before this for statement is executed? The sample code doesn't show it. cond1 and cond2 should be expressions of some sort, e.g. check_files() or feedback (feedback being a variable of some sort). The loop is going to to execute once for condition = cond1 and exitCode = 'error1'. The only thing it's going to do is check to see what condition is. Since we can assume (I hope) that cond1 is not false, then the for loop continues. Now condition = cond2 and exitCode = 'very bad error'. The if condition is still false, so the loop continues. We've come to the end now, and the else: suite is executed. We finally do some useful stuff and exitCode = good1. (Should that have been in quotes, or doesn't it matter?) But now the for loop's job is done and we return the exitCode, which at this point is good1. But I still don't understand what happens if we can't do useful stuff. Where does an error code get set, and where is that error code checked? We don't have a chance to check it in the for loop, because once we're in the else: suite the loop condition is never rechecked. Or is it? You have outlined what happens when cond1 and cond2 both evaluate to True -- what happens if, say, cond2 evaluates to False? . . . . . if not cond2 becomes True, we hit the break, do not do do_some_usefull_stuff(), but proceed to return exitCode -- and exitCode was set in the for loop to 'very bad error' when condition was set to cond2. The exitCode no longer needs to be checked inside the function, because there is no chance of do_some_useful_stuff running if any of the conditions are False. Hope this helps. ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 12/17/2010 11:13 AM, Tim Golden wrote: On 17/12/2010 15:53, Steve Holden wrote: [... snip example of for-else ...] This construct appears to be unpopular in actual use, and when it comes up in classes and seminars there is always interesting debate as people discuss potential uses and realise there are useful applications. I use this not infrequently, and I like it when it seems to be an elegant way to express the code path. But I still misremember from time to time and assume that the else clause fires when the for loop is empty. Yes, that's a common misconception. The classical use is something like for item in possibilities: if item == target: break else: raise NotFound(Didn't find it) Though of course arguably that logic might be expressed in other ways, such as if target not in possibilities: raise NotFound(Didn't find it) regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 PyCon 2011 Atlanta March 9-17 http://us.pycon.org/ See Python Video! http://python.mirocommunity.org/ Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Steve Holden st...@holdenweb.com writes: I think the choice of keyword is probably not Guido's crowning language achievement, I remember the behaviour by considering a typical application: for thing in things: if shinyp(thing): break else: raise DullError, 'nothing shiny found' In this kind of search loop, `break' signifies a kind of successful completion: the `for' loop can be considered to be a test acting over an iterable, and `else' therefore denotes the action if the test fails. I don't know whether that's the official intuition, or even if there is an official intuition, but it works well enough for me. I'm quite fond of Python's extra `else' clauses in `for' and (particularly) `try'. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Tim Golden m...@timgolden.me.uk writes: On 17/12/2010 15:53, Steve Holden wrote: [... snip example of for-else ...] This construct appears to be unpopular in actual use, and when it comes up in classes and seminars there is always interesting debate as people discuss potential uses and realise there are useful applications. I use this not infrequently, and I like it when it seems to be an elegant way to express the code path. But I still misremember from time to time and assume that the else clause fires when the for loop is empty. I use it from time to time, even though, like you, I used to always be unsure when the else: suite would be executed. I now remember this idiom as the break else construct: either the loop breaks, or the else: suite is executed. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
I now remember this idiom as the break else construct: either the loop breaks, or the else: suite is executed. A perfect description. Malcolm -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 2010-12-16, Stefan Sonnenberg-Carstens stefan.sonnenb...@pythonmeister.com wrote: The advantage in latter case is fewer operations, because you can skip the assignments, and it is more readable. The one entry, one exit is an advice. Not a law. Your code is OK. As long as it works ;-) Even that last bit isn't that important. Give me code that's easy-to-read and doesn't work rather code that works and can't be read any day. -- Grant Edwards grant.b.edwardsYow! What's the MATTER at Sid? ... Is your BEVERAGE gmail.comunsatisfactory? -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 2010-12-16, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: On Thu, 16 Dec 2010 21:49:07 +, John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode It doesn't look like you were learning Python. It looks like you were learning C with Python syntax :( Let's not blame C for bad program structure. No good C programmer would use that construct either. One choice in C would look like this: if (some_condition) return code1; if (other_condition) return code2; if (condition3) return code3; //do whatever work really needs to be done here. return successCode; Or, if there's cleanup that needs to be done, then you raise a an exception: if (condition1) { ret = code1; goto errexit; } if (condition2) { ret = code2; goto errexit; } if (condition3) { ret = code3; goto errexit; } // do the normal bit of work errexit: //cleanup return ret; -- Grant Edwards grant.b.edwardsYow! Awright, which one of at you hid my PENIS ENVY? gmail.com -- http://mail.python.org/mailman/listinfo/python-list
RE: If/then style question
-Original Message- You have outlined what happens when cond1 and cond2 both evaluate to True -- what happens if, say, cond2 evaluates to False? - I reply And the light goes on! (And palm strikes forehead.) I was thinking that the error we were processing was raised by the do_some_useful_stuff() function. But the whole purpose of this thread was to evaluate error conditions that might have been set before we do useful stuff! Which, of course, was what the original poster was asking. My thanks again for your patience. RobR -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Thu, 16 Dec 2010 21:49:07 +, John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode Another way to look at this is as question of object-oriented style, as you are using a method in your example... Arguably, rather than branching your code based on the arguments being passed to your method, you can embody the required behaviour in subclasses of your class, and at runtime just use an object that does the right thing. Of course, you end up writing the same branching in some factory object instead, but at least it isn't cluttering up your business logic any longer. Trying to write an OO-style program without using any if statements in the business logic can be an interesting exercise, albeit not a terribly realistic one. Apologies if your choice of a method for your example was entirely incidental to your question :) Kev -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Fri, 17 Dec 2010 10:53:45 -0500, Steve Holden wrote about for...else: This construct appears to be unpopular in actual use, and when it comes up in classes and seminars there is always interesting debate as people discuss potential uses and realise there are useful applications. Yes, I find I don't need it often, but it is useful from time to time. I wonder whether it would have been more useful to reverse the sense of the else, and have it run only if the for loop *didn't* run to completion. That seemed more intuitive to me, and I've wanted to do this more than once. Here's a toy example: for x in sequence: if x == spam: print(exiting early) break elif x == ham: print(exiting early) break do_something(x) would become: for x in sequence: if x == spam: break elif x == ham: break do_something(x) else: print(exiting early) I think the choice of keyword is probably not Guido's crowning language achievement, but then since the English keywords don't make natural sense to those who speak other languages it's at least fair that there should be one that isn't totally natural to English speakers. A small price to pay for all the other keywords not being Dutch. Indeed :) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Fri, 17 Dec 2010 17:26:08 +, Grant Edwards wrote: Give me code that's easy-to-read and doesn't work rather code that works and can't be read any day. Well, in that case, you'll love my new operating system, written in 100% pure Python: [start code] print(this is an operating system) [end code] I expect it to rapidly make Windows, Linux and OS-X all obsolete. Bill Gates and Steve Jobs, look out! *grin* Surely your attitude towards usefulness vs. readability will depend strongly on whether you are intending to *use* the code, or *maintain* the code? -- Steven -- http://mail.python.org/mailman/listinfo/python-list
If/then style question
(This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? Thanks. -- John Gordon A is for Amy, who fell down the stairs gor...@panix.com B is for Basil, assaulted by bears -- Edward Gorey, The Gashlycrumb Tinies -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. As far as if/else goes, I prefer the second style also. As far as returning bad codes, you are better off raising exceptions: def myMethod(self, arg1, arg2): if some_bad_condition: raise Bad1() elif some_other_bad_condition: raise Bad2() elif yet_another_bad_condition: raise Bad3() do_some_useful_stuff # no need to return 'good' code -- success means no problems ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 2010-12-16, John Gordon gor...@panix.com wrote: I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. So, take the good intentation from one and the single exit from the other: def myMethod(self, arg1, arg2): if some_bad_condition: exitCode = bad1 elif some_other_bad_condition: exitCode = bad2 elif yet_another_bad_condition: exitCode = bad3 else: exitCode = do_some_useful_stuff() # possible common cleanup code here return exitCode Or, raise an exception on bad condtions rather then passing an error code. -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 2010-12-16, John Gordon gor...@panix.com wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. There's nothing inherently wrong with indentation, but in this case the latter style is a _lot_ easier to read (and modify without breaking). However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? I think the check/exit style is far more readable. It can trip you up if there is cleanup stuff that needs to happen before you return from the function. In that case putting the whole function in a try statement and raising exceptions for the bad conditions works nicely. Then you get the more readable style of the check/exit style, plus the advantage of a single exit (it's easy to verify visually that all the required cleanup is happening). -- Grant Edwards grant.b.edwardsYow! I want a WESSON OIL at lease!! gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Am 16.12.2010 22:49, schrieb John Gordon: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 else: do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? Thanks. The advantage in latter case is fewer operations, because you can skip the assignments, and it is more readable. The one entry, one exit is an advice. Not a law. Your code is OK. As long as it works ;-) P.S.: Sorry, I could not resist: return bad1 if some_bad_condition else bad2 if some_other_bad_condition else bad3 if yet_another_bad_condition else good1 if do_some_useful_stuff() else good1 Or consider this: return [x for x,y in ((bad1,some_bad_condition),(bad2,some_other_bad_condition),(bad3,yet_another_bad_condition),(good1,do_some_useful_stuff() or True)) if x][0] Neither self explanatory nor readable :-( -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Thu, 2010-12-16 at 21:49 +, John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? one entry, one exit has its good points, but it's *way* overquoted and overused. Do you raise any exceptions? Do you call any functions that might raise exceptions? If so, you've got multiple exit points already. I think this style a lot more important in a language like C where you have to be super-careful about cleaning up after yourself. The single exit point makes it easier to verify that all cleanup tasks have been performed. Assuming you're using with or try-finally then you just don't need such guarantees in python. I'm not a PEP-8 pedant by any means, but I think that the first section of PEP-8 contains the best advice I've ever read about programming language style. In fact, I'm going to quote it right here: A Foolish Consistency is the Hobgoblin of Little Minds == One of Guido's key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As PEP 20 says, Readability counts. ...snip... But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask! In your example, the first style is difficult to read wile the second style is easy to read. You don't need any further justification for preferring the latter. Cheers, Ryan -- Ryan Kelly http://www.rfk.id.au | This message is digitally signed. Please visit r...@rfk.id.au| http://www.rfk.id.au/ramblings/gpg/ for details signature.asc Description: This is a digitally signed message part -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Thu, Dec 16, 2010 at 3:41 PM, Stefan Sonnenberg-Carstens stefan.sonnenb...@pythonmeister.com wrote: return [x for x,y in ((bad1,some_bad_condition),(bad2,some_other_bad_condition),(bad3,yet_another_bad_condition),(good1,do_some_useful_stuff() or True)) if x][0] This doesn't work. do_some_usefull_stuff() gets called during the tuple construction regardless of the conditions, not during the list comprehension execution as you would want. Here's my take on an unreadable one-liner: return reduce(lambda x, y: (x or (y[0]() and y[1])), [(some_bad_condition, bad1), (some_other_bad_condition, bad2), (yet_another_bad_condition, bad3), (lambda: (do_some_useful_stuff() or True), good1)], None) This of course assumes that bad1, bad2, and bad3 all evaluate as true. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Thu, 16 Dec 2010 21:49:07 +, John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode It doesn't look like you were learning Python. It looks like you were learning C with Python syntax :( The above would be more Pythonically written as: def myMethod(self, arg1, arg2): if not some_good_condition: raise SomeException(message) if not some_other_good_condition: raise SomeOtherException(another message) if yet_another_good_condition: do_some_useful_stuff() else: raise SomeThirdException(whatever) using exceptions to communicate errors out-of-band. Since no return result is needed, no explicit return is used and the method is the closest thing to a procedure that Python can offer. The problem with in-band transmission of errors is that they invite the anti-pattern of this: result = obj.myMethod(arg1, arg2) if result == good1: do_something_good() elif result == bad1: handle_error1() elif result == bad2: handle_error2() elif result == bad3(): handle_error3() else: print This can't ever happen, but if it does... which all too often becomes: result = obj.myMethod(arg1, arg2) if result == good1: do_something_good() else: # assume result is bad1 handle_error1() or even: who_cares = obj.myMethod(arg1, arg2) do_something_good() But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. Well, that's better, but still more like C rather than Python. Avoid the anti-pattern of returning in-band error codes. In some languages, either exceptions aren't available at all, or the overhead of them is so great that for performance you have to avoid them, but Python is not one of those languages. In Python, exceptions are *the* primary way of communicating exceptional cases such as (but not limited to) errors. I can only think of two, er, exceptions to this rule: str.find() and some of the regular expression methods. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Functions always have one entry. The only way to have multiple entry points is if the language allows you to GOTO into the middle of a function, and Python sensibly does not allow this. The one entry, one exit rule comes from the days when people would routinely write spaghetti code, jumping into and out of blocks of code without using functions at all. If one entry is pointless (all functions have one entry!) then one exit is actively harmful. It leads to adding unnecessary complexity to functions, purely to meet the requirements of a rule invented to discourage spaghetti code. This hides bugs and increases the maintenance burden. Don't get me wrong... spaghetti code is *bad*. But there are other ways of writing bad code too, and hanging around inside a function long after you've finished is also bad: def function(arg): done = False do_something() if some_condition: result = finished done = True if not done: do_something_else() if another_condition: result = now we're finished done = True if not done: do_yet_more_work() if third_condition: result = finished this time for sure done = True if not done: for i in range(100): if not done: do_something_small() if yet_another_condition: result = finally done! done = True return result It's far more complicated than it need be, and does *lots* of unnecessary work. This can be written more simply and efficiently as: def function(arg): do_something() if some_condition: return finished do_something_else() if another_condition: return now we're finished do_yet_more_work() if third_condition: return finished this time for sure for i in range(100): do_something_small() if yet_another_condition: return finally done! Over 40% of the code in the first version
Re: If/then style question
John Gordon gor...@panix.com wrote: But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 For more than 2 tests in a function like this, I'd probably use dictionary dispatch: def myMethod(self, arg1, arg2): branches = dict( cond1: bad1, cond2: bad2, cond3: bad3 ) cond = expression if cond == cond_good: do_some_useful_stuff() exitCode = good1 else: exitCode = branches[cond] return exitCode -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote in message news:4d0aa5e7$0$29997$c3e8da3$54964...@news.astraweb.com... It doesn't look like you were learning Python. It looks like you were learning C with Python syntax :( True, although in many cases one has to interface to legacy C code where it'd be rather more code to start throwing exceptions left or right... since sooner or later those exceptions would still have to be turned into a single status (error) code! which all too often becomes: result = obj.myMethod(arg1, arg2) if result == good1: do_something_good() else: # assume result is bad1 handle_error1() This really isn't a bad way to go *if you weren't planning on spending the time to really, fully flesh out the individual error cases anyway.* I see this pretty often: Peple put in sophisticated exception handling infrastructure, but when an error actually occurs, all six dozen cases handled individually end up just printing some generic message and exiting the program anyway. In an ideal world all the error cases would do something smart, but pragmatically one has to balance how likely an error is to occur and how much damage it does with how much time you want to spend making a really smart error handler. or even: who_cares = obj.myMethod(arg1, arg2) do_something_good() Even this can be OK if do_something_good() behaves in a relatively benign fashion when feed gibberish. I mean, how many people actually check to see whether or not printf() succeeded, you know? But I would agree that often you see... who_care = obj.myMethod(arg1, arg2) do_something_really_dangerous_that_depends_on_the_success_of_myMethod() :-) Well, that's better, but still more like C rather than Python. Avoid the anti-pattern of returning in-band error codes. The main sticky point here is that what's an error vs. a warning or note (but not success) is often rather a grey area. E.g., Pyhton's open() raises an IOError is the file can't be opened, but in my mind that's still a common enough/expected occurrence that elevating its behavior to an exception is more a judgement call than something everyone would agree on. (On the other hand, trying to read or write to an un-opened file is now clearly in the realm of an error and deserves an exception.) ---Joel -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On Dec 16, 2:56 pm, Ryan Kelly r...@rfk.id.au wrote: On Thu, 2010-12-16 at 21:49 +, John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? one entry, one exit has its good points, but it's *way* overquoted and overused. Do you raise any exceptions? Do you call any functions that might raise exceptions? If so, you've got multiple exit points already. I think this style a lot more important in a language like C where you have to be super-careful about cleaning up after yourself. The single exit point makes it easier to verify that all cleanup tasks have been performed. Assuming you're using with or try-finally then you just don't need such guarantees in python. Even without the cleanup issue, sometimes you want to edit a function to affect all return values somehow. If you have a single exit point you just make the change there; if you have mulitple you have to hunt them down and change all of them--if you remember to. I just got bit by that one. It's a trade-off. Readability and/or conciseness versus error robustness. I tend to go for the former but mileage varies. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: If/then style question
On 12/16/2010 11:32 PM, Carl Banks wrote: On Dec 16, 2:56 pm, Ryan Kelly r...@rfk.id.au wrote: On Thu, 2010-12-16 at 21:49 +, John Gordon wrote: (This is mostly a style question, and perhaps one that has already been discussed elsewhere. If so, a pointer to that discussion will be appreciated!) When I started learning Python, I wrote a lot of methods that looked like this: def myMethod(self, arg1, arg2): if some_good_condition: if some_other_good_condition: if yet_another_good_condition: do_some_useful_stuff() exitCode = good1 else: exitCode = bad3 else: exitCode = bad2 else: exitCode = bad1 return exitCode But lately I've been preferring this style: def myMethod(self, arg1, arg2): if some_bad_condition: return bad1 elif some_other_bad_condition: return bad2 elif yet_another_bad_condition: return bad3 do_some_useful_stuff() return good1 I like this style more, mostly because it eliminates a lot of indentation. However I recall one of my college CS courses stating that one entry, one exit was a good way to write code, and this style has lots of exits. Are there any concrete advantages of one style over the other? one entry, one exit has its good points, but it's *way* overquoted and overused. Do you raise any exceptions? Do you call any functions that might raise exceptions? If so, you've got multiple exit points already. I think this style a lot more important in a language like C where you have to be super-careful about cleaning up after yourself. The single exit point makes it easier to verify that all cleanup tasks have been performed. Assuming you're using with or try-finally then you just don't need such guarantees in python. Even without the cleanup issue, sometimes you want to edit a function to affect all return values somehow. If you have a single exit point you just make the change there; if you have mulitple you have to hunt them down and change all of them--if you remember to. I just got bit by that one. It's a trade-off. Readability and/or conciseness versus error robustness. I tend to go for the former but mileage varies. Heaven forfend you should just wrap the existing function inside another one which takes its name, if all its returns need to be altered. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 PyCon 2011 Atlanta March 9-17 http://us.pycon.org/ See Python Video! http://python.mirocommunity.org/ Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
K-Dawg wrote: I am trying to become more pythonic as I learn python and get my mind around it instead of other languages I have used. I have an app that has a series of classes for objects it uses. From a style perspective, which should be done: Different py file for each class or One py file with all the classes The classes are small with a constructor and a few methods, no more than a couple, some with just one other method. Which is more pythonic? One .py file with all the classes. But it's also very pythonic that you have the choice, and can select the option that suits you best ;-) regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Python Style Question
Steve Holden wrote: K-Dawg wrote: I am trying to become more pythonic as I learn python and get my mind around it instead of other languages I have used. I have an app that has a series of classes for objects it uses. From a style perspective, which should be done: Different py file for each class Python is not Java! or One py file with all the classes The classes are small with a constructor and a few methods, no more than a couple, some with just one other method. Or if that gets to be too much, a few files each with several related classes. Which is more pythonic? One .py file with all the classes. But it's also very pythonic that you have the choice, and can select the option that suits you best ;-) Nice put Steve. tjr -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
On Jan 9, 11:51 pm, Fredrik Lundh [EMAIL PROTECTED] wrote: Steve Brown wrote: I've got a series of modules which look like this: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test I don't like the duplicated information: But the comment is attractive, and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. I don't think that Temperature Sense Test class Test3(ar_test.AR_TEST): Temperature Sense Test would be a real improvement. What do you think? since you already seem to cater to your audience (clearly marked comments for people browsing the code, brief docstrings for the test log), I don't really see why you should change anything. I've read that all modules and classes should have docstrings if nobody's going to read them, there's no reason to add them. don't treat generic style advice as dogma. /F Well, trivial modules certainly don't need much documentation, but he didn't say they were trivial. I assumed there was more to them then he showed. -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
-On [20080110 06:51], Steve Brown ([EMAIL PROTECTED]) wrote: I don't like the duplicated information: But the comment is attractive, I find it unattractive to be honest. and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. The ultimate test is running `pydoc your.module` or running epydoc on your source and see how well the resulting documentation is built up. -- Jeroen Ruigrok van der Werven asmodai(-at-)in-nomine.org / asmodai イェルーン ラウフロック ヴァン デル ウェルヴェン http://www.in-nomine.org/ | http://www.rangaku.org/ The quieter you become, the more you are able to hear... -- http://mail.python.org/mailman/listinfo/python-list
RE: docstrings style question
On Behalf Of Steve Brown What do you think? I think that comments are for maintainers, and docstrings are for users. Some of the things I use comments for: * Visually separate classes (using a syntax-highlighting editor) * Explain algorithm choices * Explain bug fixes so I don't later fix code back to the buggy version Some of the things I use docstrings for: * Describe interface (inputs/outputs) * Sample usage I personally don't use doctests, but that's one more use of docstrings. Regards, Ryan Ginstrom -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
Russ P. wrote: On Jan 9, 9:47 pm, Steve Brown [EMAIL PROTECTED] wrote: I've got a series of modules which look like this: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test I don't like the duplicated information: But the comment is attractive, and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. I don't think that Temperature Sense Test class Test3(ar_test.AR_TEST): Temperature Sense Test would be a real improvement. What do you think? It's still duplicated information. I tend to be a bit skimpy with one-line comments for classes and methods, but I think a more complete ( style) comment is often appropriate for the top of the file. I'm sure you can think of more to say than Temperature Sense Test. exactly my opinion What temperature? What kind of temperature sensor? What kind of test is it, and why are you doing it? That may all be obvious in context, but you've provided no context in your post. Also, if the module is of any significant size, you might want to provide a clue about who wrote it. Then, if someone has a question about it later, they will know who to ask. I tend to mention the main use cases for test classes (especially) and also a human readable description of what can happen (forgive me the missing line breaks). Something like this: class Test3(ar_test.AR_TEST): Temperature Sense Test. This class assures that the connection to the hardware sensor can be established. It also checks a reference sensor that always reports a certain value so that one can be sure correct data values are reported. hth martin -- http://noneisyours.marcher.name http://feeds.feedburner.com/NoneIsYours You are not free to read this message, by doing so, you have violated my licence and are required to urinate publicly. Thank you. -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
Russ P. [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On Jan 9, 11:51 pm, Fredrik Lundh [EMAIL PROTECTED] wrote: Steve Brown wrote: I've got a series of modules which look like this: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test I don't like the duplicated information: But the comment is attractive, and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. I don't think that Temperature Sense Test class Test3(ar_test.AR_TEST): Temperature Sense Test would be a real improvement. What do you think? since you already seem to cater to your audience (clearly marked comments for people browsing the code, brief docstrings for the test log), I don't really see why you should change anything. I've read that all modules and classes should have docstrings if nobody's going to read them, there's no reason to add them. don't treat generic style advice as dogma. /F Well, trivial modules certainly don't need much documentation, but he didn't say they were trivial. I assumed there was more to them then he showed. All of the complexity is in the test framework. I've been working on paring back the tests to make them simple to understand, create and modify, which is how I've come to this: I'm still trying to remove lines. The test itself is a now a linear script of 20-40 lines, and I'm still working on them. However, it is relatively important to make the documentation right for these simple scripts. The docstring/comment does need to show some embedded dependancies, I just chose one without any. I realise from reading Jeroen Ruigrok van der Werven's comment that I should probably also care what epydoc makes of my doc strings, -- that's an additional constraint. -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
On Jan 10, 2008 12:47 AM, Steve Brown [EMAIL PROTECTED] wrote: I've got a series of modules which look like this: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test I don't like the duplicated information: But the comment is attractive, and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. I don't think that Temperature Sense Test class Test3(ar_test.AR_TEST): Temperature Sense Test would be a real improvement. What do you think? I recommend a careful reading of PEP 257. You shouldn't waste your time creating (at best) decorative comments, like: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test Remember that comments have to maintained along with the rest of the code, so unnecessary ones just create more work for you. Any time you can replace a comment with self-explanatory code, you should. Here's a vast improvement: class TemperatureSenseTester(ar_test.AR_TEST): -- Neil Cerutti [EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
Neil Cerutti [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On Jan 10, 2008 12:47 AM, Steve Brown [EMAIL PROTECTED] wrote: I've got a series of modules which look like this: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test I don't like the duplicated information: But the comment is attractive, and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. I don't think that Temperature Sense Test class Test3(ar_test.AR_TEST): Temperature Sense Test would be a real improvement. What do you think? I recommend a careful reading of PEP 257. You shouldn't waste your time creating (at best) decorative comments, like: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test Remember that comments have to maintained along with the rest of the code, so unnecessary ones just create more work for you. Any time you can replace a comment with self-explanatory code, you should. Here's a vast improvement: class TemperatureSenseTester(ar_test.AR_TEST): -- Neil Cerutti [EMAIL PROTECTED] Yes, I'm working in that direction. At present there is still code that parses the test sequence to get the class name, but I'm rebuilding that. However, there will still be sufficient information for some of the tests to justify one doc string or comment as well as the class name. Is it possible to get from an object to a class module doc string? Something like self.class.module.__doc__ ? I'm not able to do an assignment inside the test class, because I have to keep that clean, but I can do assignments inside the parent test class. Steve -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
What I'm trying to do with the tests is pare them back so that the code explicitly and concisely documents the tests. It is important that the comments and doc strings NOT contain information about how Temperature Sense works because that is outside the scope of the test. More generally, comments like this i++#increments i indicate that the author thinks that the most complex thing present is the syntax, a comment like this: i++#next voltage indicates that the author thinks the most complex thing present is the variable mapping. For the readers and maintainers of these tests, the most complex thing present is the syntax, not the test logic, so if I need to add more documentation, it will look like this: # Temperature Sense Test # Lines starting with # are comments # Variables are case sensitive # Tab characters will break this file -- and go from there. Steve Martin Marcher [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] Russ P. wrote: -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
On Fri, 11 Jan 2008 13:09:26 +1100, Steve Brown wrote: What I'm trying to do with the tests is pare them back so that the code explicitly and concisely documents the tests. Yes, this is good. It is important that the comments and doc strings NOT contain information about how Temperature Sense works because that is outside the scope of the test. More generally, comments like this i++#increments i indicate that the author thinks that the most complex thing present is the syntax, I would suggest that it indicates an author who hates writing documentation, but has been told that (s)he *must* do it. That is the archetypal example of the pointless comment that is worse than no comment at all. a comment like this: i++#next voltage indicates that the author thinks the most complex thing present is the variable mapping. To me, that indicates the author both hates writing documentation, and either can't think of descriptive variable names, or refuses to use them out of some misguided sense of optimization. For the readers and maintainers of these tests, the most complex thing present is the syntax, not the test logic, so if I need to add more documentation, it will look like this: # Temperature Sense Test # Lines starting with # are comments # Variables are case sensitive # Tab characters will break this file -- and go from there. Your trusting your production code to developers who don't even know the most basic elements of syntax like what is a comment? That's pretty foolh^H^H^H^H^H brave. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: docstrings style question
Steve Brown wrote: I've got a series of modules which look like this: # # # Temperature Sense Test # # class Test3(ar_test.AR_TEST): Temperature Sense Test I don't like the duplicated information: But the comment is attractive, and the docstring self.__doc__ is already in use in the test log. I've read that all modules and classes should have docstrings, but I don't really have anything else to say, and each module contains only one class. I don't think that Temperature Sense Test class Test3(ar_test.AR_TEST): Temperature Sense Test would be a real improvement. What do you think? since you already seem to cater to your audience (clearly marked comments for people browsing the code, brief docstrings for the test log), I don't really see why you should change anything. I've read that all modules and classes should have docstrings if nobody's going to read them, there's no reason to add them. don't treat generic style advice as dogma. /F -- http://mail.python.org/mailman/listinfo/python-list
Non-ASCII languages (was: Re: style question)
On Thu, 29 Jun 2006 23:19:34 +0200, Fredrik Lundh [EMAIL PROTECTED] wrote: Jorgen Grahn wrote: ... (I like well-typeset code in print though. Bjarne Stroustrup uses an elegant system for C++ code, where identifiers and strings are in Times italic, operators in Courier, and so on.) the idea of printing everything in courier (or some other monospace font) is a rather new idea; if you read seventies stuff, the program code is often as carefully designed as the rest of the document. Possibly true, and definitely for Knuth. But WYSIWYG was unknown at the time; these people all programmed using fixed-width fonts, on teletypes or character-mapped terminals. Hell, even full-screen editors were new and controversial until the late 1970s! Program editing and displaying/typesetting can be treated as separate from each other. Personally, I think they /should/ be -- I prefer troff or LaTeX to MS Word, after all. (for an indication that we might be moving back to nicely rendered code, see Sun's new Fortress language, which provides extraordinarily detailed control over how identifiers are rendered, including extensive support for Unicode and math notation. it also mandates the use of proportional fonts for things like identifiers and comments...) And Sun apparently think they should not be separate. To me, it looks like they are planning for this language to fail. If I wanted to try out this language, I would have to give up most of my existing toolbox -- which works flawlessly with everything from TI assembly to Python. And what would people discuss on comp.lang.fortress? Google destroys Python code well enough ... /Jorgen -- // Jorgen Grahn grahn@Ph'nglui mglw'nafh Cthulhu \X/ snipabacken.dyndns.org R'lyeh wgah'nagl fhtagn! -- http://mail.python.org/mailman/listinfo/python-list
Re: Non-ASCII languages (was: Re: style question)
In article [EMAIL PROTECTED], Jorgen Grahn [EMAIL PROTECTED] writes: | | Possibly true, and definitely for Knuth. But WYSIWYG was unknown at the | time; these people all programmed using fixed-width fonts, on teletypes or | character-mapped terminals. Hell, even full-screen editors were new and | controversial until the late 1970s! A slight niggle - WYSIWYG wasn't unknown, just both rare and not yet called that! I have programmed using devices with half-line shifts, real backspacing and so on - and some languages did mandate that a character created by overprinting was to be treated as a composite character. Also, there were full-screen editors for things like IBM 3270s, though they were absolutely ghastly for editing text (being designed for form filling). I agree with you that neither those days nor gimmicky approaches like that of Fortress are worth pursuing. One of the main reasons that 'program proving' has never taken off outside its cabal is that it uses bizarre notations unlike anything else on earth that can't be edited in a normal fashion. Regards, Nick Maclaren. -- http://mail.python.org/mailman/listinfo/python-list
calling functions style question
I just have a basic style question here. Suppose you have the program: def foo1(): do something def foo2() do something else Assume that you want to call these functions at execution. Is it more proper to call them directly like: foo1() foo2() or in an if __name__ == __main__: ? Both will execute when the script is called directly, I was just wondering if there is a preference, and what the pros and cons to each method were. Thanks, Brian -- http://mail.python.org/mailman/listinfo/python-list
Re: calling functions style question
The difference becomes clear when you import your program into another program (or the command line python editor). __name__!='__main__' when you import, so the functions will not be called if they're inside the block. This is why you see this block so often at the end of scripts; so that the script runs its main functions when called as a standalone program, but you can also import the code and do something with it without setting off those functions. THN Brian wrote: I just have a basic style question here. Suppose you have the program: def foo1(): do something def foo2() do something else Assume that you want to call these functions at execution. Is it more proper to call them directly like: foo1() foo2() or in an if __name__ == __main__: ? Both will execute when the script is called directly, I was just wondering if there is a preference, and what the pros and cons to each method were. Thanks, Brian -- http://mail.python.org/mailman/listinfo/python-list
Re: calling functions style question
Brian wrote: I just have a basic style question here. Suppose you have the program: def foo1(): do something def foo2() do something else Assume that you want to call these functions at execution. Is it more proper to call them directly like: foo1() foo2() or in an if __name__ == __main__: ? Both will execute when the script is called directly, I was just wondering if there is a preference, and what the pros and cons to each method were. Thanks, Brian If you want those functions to be called each time your module gets imported you have to apply calls out of the if __name__ ... statement. If your module is, for certain reasons, always the __main__ module and never gets imported there is no obvious preference because behaviour will be the same. -- http://mail.python.org/mailman/listinfo/python-list