Back again on f-strings - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Back again on f-strings (/thread-21805.html) Pages:
1
2
|
Back again on f-strings - newbieAuggie2019 - Oct-15-2019 Hi! It seems that I cannot fully understand f-strings. I do exercises and little programs trying to update them by using f-strings, but now and then, I keep having some problems. For instance, I wrote this little program: # atbs_04_commaCode_01.py # # It works. # def commaCode(list1): print("'", end='') print(*list1[:-1], sep=', ', end=",") print(' and', list1[-1], end=".'\n\n") spam1 = ['apples', 'bananas', 'tofu', 'cats'] commaCode(spam1) eggs1 = ['bird', 'dolphin', 'whale', 'parrot', 'gorilla', 'dog'] commaCode(eggs1) numbers1 = [1, 2, 3, 4, 5] commaCode(numbers1)that works and produces the following output: 1) Is there a way to simplify the 3 lines of print with f-strings?2) Is there a good tutorial FOR DUMMIES or FOR NEWBIES on all the details of f-strings? I like Metulburr's basic tutorial: https://python-forum.io/Thread-Basic-f-string-string-format-and-string-expressions I wish there would be a longer, deeper one, but easy enough to follow and understand by thickheads like myself. Thanks and all the best, RE: Back again on f-strings - perfringo - Oct-15-2019 Something like this? EDIT: initially didn't notice 'and' >>> spam1 = ['apples', 'bananas', 'tofu', 'cats'] >>> print(f"'{', '.join(spam1)}.'") 'apples, bananas, tofu, cats.'Version with 'and': >>> print(f"'{', '.join(spam1[:-1])}, and {spam1[-1]}.'") 'apples, bananas, tofu, and cats.'Newlines can be added outside the curled brackets. RE: Back again on f-strings - buran - Oct-15-2019 def print_nicely(iterable): iterable = list(map(str, iterable)) if len(iterable) > 1: print(f"'{', '.join(iterable[:-1])} and {iterable[-1]}'") elif len(iterable) == 1: print(f"'{iterable[0]}'") else: raise ValueError('Expecting non-empty iterable') print_nicely(['apples', 'bananas', 'tofu', 'cats']) # print list print_nicely(['bird']) # print single element list print_nicely(range(4)) # print range object print_nicely([]) by the way i may have seen a package on PyPI that does it but cannot find it at the moment
RE: Back again on f-strings - newbieAuggie2019 - Oct-15-2019 (Oct-15-2019, 09:50 AM)perfringo Wrote: Something like this? EDIT: initially didn't notice 'and'Thanks a lot! I saw your version, just before you added the version with 'and' and I modified my code accordingly, but then I realized it didn't work the same way. I thought it was I had mistyped something, but later I noticed that it was not the code, but the lists (in plural) that I had. The 3 lists are different. The first 2 ones are formed by string elements, while the 3rd one is formed by integers, so I could understand then the error message: def commaCode(list1): print(f"'{', '.join(list1[:-1])}, and {list1[-1]}.'") spam1 = ['apples', 'bananas', 'tofu', 'cats'] commaCode(spam1) eggs1 = ['bird', 'dolphin', 'whale', 'parrot', 'gorilla', 'dog'] commaCode(eggs1) numbers1 = [1, 2, 3, 4, 5] commaCode(numbers1)
But in theory, my function should be able to work with any list value passed to it.How should I approached this inconvenience? Should I leave it then with the 3 print lines? Is it OK to leave it with the 3 print lines? Thanks and all the best, RE: Back again on f-strings - buran - Oct-15-2019 I found it https://github.com/jazzband/inflect import inflect p = inflect.engine() print(p.join(['apples', 'bananas', 'tofu', 'cats'])) # print list print(p.join(['bird'])) # print single element list print(p.join(list(map(str, range(4))))) # print range object print(p.join([]))
RE: Back again on f-strings - newbieAuggie2019 - Oct-15-2019 (Oct-15-2019, 10:00 AM)buran Wrote:def print_nicely(iterable): iterable = list(map(str, iterable)) if len(iterable) > 1: print(f"'{', '.join(iterable[:-1])} and {iterable[-1]}'") elif len(iterable) == 1: print(f"'{iterable[0]}'") else: raise ValueError('Expecting non-empty iterable') print_nicely(['apples', 'bananas', 'tofu', 'cats']) # print list print_nicely(['bird']) # print single element list print_nicely(range(4)) # print range object print_nicely([])by the way i may have seen a package on PyPI that does it but cannot find it at the moment Thanks a lot! Although I like your creative way of thinking, in this case, you have transformed the 4 lines I wanted to simplify, using f-strings: def commaCode(list1): print("'", end='') print(*list1[:-1], sep=', ', end=",") print(' and', list1[-1], end=".'\n\n")into actually 8 lines of code (maybe 6 if we eliminate the last 2 lines): def print_nicely(iterable): iterable = list(map(str, iterable)) if len(iterable) > 1: print(f"'{', '.join(iterable[:-1])} and {iterable[-1]}'") elif len(iterable) == 1: print(f"'{iterable[0]}'") else: raise ValueError('Expecting non-empty iterable')I think that as I don't know about 'map()', I prefer Perfringo's one liner in this case, but I have not sorted out the problem with the numerical list yet. Thanks and all the best, (Oct-15-2019, 10:37 AM)buran Wrote: I found it Thanks a lot! That looks to me much clearer than the other one. Thanks and all the best, RE: Back again on f-strings - buran - Oct-15-2019 Mine is longer because it handles more cases, e.g. it can handle list with numerical values, range objects, generators, single element containers, empty containers, etc. If I just replicate your code (and inherent problems) it will be a one liner. def print_nicely(iterable): print(f"'{', '.join(iterable[:-1])} and {iterable[-1]}'")or to fully replicate your code (which will handle also the range/list with numerical values): def print_nicely(iterable): print(f"'{', '.join(str(item) for item in iterable[:-1])} and {str(iterable[-1])}'")for example try with your code to print generator expression or empty list or single element list for empty list will get IndexError, for generator expression - TypeError, single element list will look ugly ', and bird.' if you are not familiar with map() you can use list comprehension instead (I've seen that Guido is in favour of comprehension compared to map) iterable = [str(item) for item in iterable] RE: Back again on f-strings - perfringo - Oct-15-2019 I agree with buran that his solution is more life-like than oneliner and therefore longer. One should be defensive and/or generalise (duck-typing) when writing functions. In this particular case - you can through any iterable to it and it behaves as expected. Little longer code now, lot of time saved on debugging in the future. RE: Back again on f-strings - newbieAuggie2019 - Oct-15-2019 (Oct-15-2019, 10:37 AM)buran Wrote: I found it Thanks a lot for your time and explanations! I modified my code according to yours (after installing 'inflect'): import inflect def commaCode(list1): p = inflect.engine() print(p.join(list1)) # print list spam1 = ['apples', 'bananas', 'tofu', 'cats'] commaCode(spam1) eggs1 = ['bird', 'dolphin', 'whale', 'parrot', 'gorilla', 'dog'] commaCode(eggs1) numbers1 = [1, 2, 3, 4, 5] commaCode(numbers1)and when I ran it:
(Oct-15-2019, 11:09 AM)buran Wrote: Mine is longer because it handles more cases, e.g. it can handle list with numerical values, range objects, generators, single element containers, empty containers, etc. If I just replicate your code (and inherent problems) it will be a one liner. The only case your code would handle is the range/list with numerical values I guess that's why I get that
(Oct-15-2019, 11:09 AM)buran Wrote: for example try with your code to print generator expression or empty list or single element listNot sure what's a generator expression. (Oct-15-2019, 11:09 AM)buran Wrote: if you are not familiar with map() you can use list comprehension instead (I've seen that Guido is in favour of comprehension compared to map)I'm really ashamed of myself for my still lack of knowledge. Not sure either of what's a list comprehension, but I think I can get it with your example. (Oct-15-2019, 10:37 AM)buran Wrote: I found it Very interesting! Thanks also for that!!! Quote:[ ... ] convert numbers to words https://pypi.org/project/inflect/ Thanks and all the best, RE: Back again on f-strings - buran - Oct-15-2019 inflect will not handle list with numerical values, range object or generator expressions. you need to preprocess these and convert to list/tuple with str elements. That's why you get the first error |