11 ms·
Python built-ins worth learning (2019)
- somezero 5y agoheapq exposes a minheap by default, but there is a maxheap as well that for some reason, is not exposed! Just do heapq._heapify_max
- tony-allan 5y agoI would add f-strings to the list and some of the string methods especially .strip(), .split(), and .join()
- mkaic 5y agof-strings are so incredibly handy!
- sixstringtheory 5y agoFavorite thing I learned recently was that instead of doing print (f’some_var: {some_var}’) one can just do print (f’{some_var=}’) What’s the next cool thing I should know about f-strings?
- tony-allan 5y agoI hadn't come across f'{some_var=}' before. Output looks like: some_var='abcd' Great find!
- evgenyp 5y agoIt's even more useful for complex expressions e.g. f'{f(x, y)=}' -> 'f(x, y)=5'
- blt 5y agoIn case anyone is wondering how they missed this: The feature was added in Python 3.8, so it wasn't part of the original f-strings feature set. https://docs.python.org/3/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging https://docs.python.org/3/whatsnew/3.8.html#f-strings-suppor...
- jpm48 5y agoWow, didn't know this one (just added to my lecture notes!) thanks
- deleted 5y ago[deleted]
- minimaxir 5y agoThe reason f-strings are not as popular is because they were added in 3.6 and no one could use them for backward compatibility reasons. Now that 3.7 is the minimum supported version, it's safe to use.
- xapata 5y agoF-strings are the reason I upgraded all my projects.
- ehsankia 5y agowe also FINALLY got removeprefix() and removesuffix()! no more strange `string[:len(suffix)]`
- oneoff786 5y agoFor me, Specifically f”{x:,}” to return the value of x as a comma separated number string
- camel_Snake 5y agofwiw `format(x, ',')` will do this too and looks a bit more readable imo
- oneoff786 5y agoI think that holds true for just x, but not for, say, f”Total Cost: {round(x / 1000000, 1):,}M”
- texaslonghorn5 5y agoInteresting site, I liked it. I learned about vars and I keep forgetting dir. Only thing is that unvisited links are stylized as purple so I was slightly confused by the first three links I encountered.
- chrismorgan 5y agoI didn’t know about breakpoint(), which landed in 3.7, about a year after I stopped using Python regularly (I considered myself an expert at the time; now, the ecosystem has moved on enough and I’m rusty enough that I’d rate myself below expert, but able to become expert again in a very short time). Until hearing about this, if I were needing to debug Python stuff I’d have been perfectly happy continuing to use pdb.set_trace(), but breakpoint() is nicer now that I know about it. This reveals something important that is easy to overlook: while you’re actively working in an ecosystem, you may hear about new things that come along, but if you spend some time away, things may well happen that you didn’t hear about, and so in some cases beginners may even surpass you in current idioms. It’s worthwhile, in such cases, at least skimming over some materials and especially the release notes since you were last an expert—if I were going back to working with Python/Django extensively, I’d read at the very least the headings of the release notes for Python 3.6–3.10 and Django 1.8–.
- recuter 5y agoWhich language(s) did you switch to?
- chrismorgan 5y agoPersonally, Rust; professionally, mostly web frontend stuff (HTML/CSS/JavaScript, plenty of each) rather than Python web backend stuff.
- JNRowe 5y agoI tend to drift in and out of Python, and follow the same pattern as you suggest when coming back after a couple of releases. Python's version notes are truly excellent¹. The only thing I really wish for is an ecosystem "what's now" guide, it would list things such as where the community has moved for common libraries. Off the top of my head it would have covered things like nose to pytest and such. Obvious problem being I just can't imagine how you'd get buy-in to make such a thing work, especially without it getting overrun with grifters. ¹ https://docs.python.org/3/whatsnew/index.html https://docs.python.org/3/whatsnew/index.html
- luckman212 5y agoStructural Pattern Matching[0] (PEP 636) that landed in 3.10 was a pretty nice addition too. [0] https://peps.python.org/pep-0636/ https://peps.python.org/pep-0636/
- Buttons840 5y ago# Instead of doing this if len(numbers) == 0: print("The numbers list is empty") # Many of us do this if not numbers: print("The numbers list is empty") I tend to write the first form because it is how I think, and I'm writing what I think. "If this list is empty, then..." I suppose a list is only falsy if it is empty. I used to exploit Python's truthyness / falsyness a lot more, but now I like to be more explicit. Ultimately it doesn't matter much, making a single line a tiny bit longer is rarely the most important issue in a project.
- adhocmobility 5y agoThe second case is preferable if numbers is an Optional[List], which is usually the case when passing lists around as arguments. def custom_sum(numbers: Optional[List[int]] = None) -> int: if not numbers: ## something return sum(numbers) This can handle both cases - if numbers is None, or numbers is []
- actually_a_dog 5y agoWouldn't it be easier to say if numbers == []: print ("The numbers list is empty") if your intent is to express "is the list empty?" in the condition?
- sritchie 5y agoThat condition would fail on non-list sequences, like `numbers == (1,2,3)`; the `len` version makes the code more permissive.
- mturmon 5y agoI often use the same if len() construct. It will fail for non-list inputs, which is another reason it can be handy if you want clarify that you’re enforcing a list.
- Buttons840 5y agoAh yes, that's another reason I do it, but I failed to mention. If you see "if not x:" then you're left wondering what x is (a boolean presumably), but "if len(x) == 0:" let's you know you're checking to see if a container is empty.
- macintux 5y agoI got confused at the very start: > What’s the best way to learn the functions we’ll need day-to-day like enumerate and range? Day to day? I don’t think I’ve used either, or needed either, over the last several thousand lines of Python I’ve written. Why would those functions be particularly useful?
- whalesalad 5y agoFunny, I use them quite often. Enumerate will let you iterate anything iterable while also giving you your current index. for idx, item in enumerate(foo): if idx > 100: break otherwise() I use the above example all the time to pluck the first few items from a generator when debugging, for instance. A generator is something that hasn’t been fully actualized, it might be an infinite list or streams for example. Logging is also fun: for idx, item in enumerate(thing): logger.info(f’item {idx}: {item!r}’) yield item This could be used to wrap an existing iterator to just log each element with a counter prefixed. Also a handy debug tool. range() is useful when you want an iterable of N size. for i in range(num_tasks_to_create): foo() It can be used in this way to “do this thing N times” Or you can use it other ways like: if year in range(2000, 2020): tl;dr I can think of a half dozen ways to use either!
- macintux 5y agoAha, thanks, I do occasionally need an index.
- memco 5y agoCheck out more-itertools which has things like take, tail and a bunch of other nice functions for working with iterators if you haven’t. Would allow you to do something like for el in take(100, iter): print(el) Plus there’s a bunch of other things in there for windowing, finding out whether or where empty stuff in the generator are. https://more-itertools.readthedocs.io/ https://more-itertools.readthedocs.io/
- whalesalad 5y ago
- faizshah 5y agoA built in a lot of people don’t know is operator.itemgetter and operator.attrgetter they can be used together with functools and itertools for a lot of purposes for example you can sort a list of tuples using operator.itemgetter and sort: https://docs.python.org/3/library/operator.html https://docs.python.org/3/library/operator.html
- whalesalad 5y agoWoah the other operators are even more interesting to me. My goto is an in-line lambda to avoid the import but I didn’t realize there were so many operators defined in the stdlib. Thanks for sharing.
- heinrich5991 5y agoHm, I didn't know about those. At first I thought that I'd just replace it with a lambda, but it seems to support looking up multiple elements/members at the same time, so that might come in handy at some point.
- ehsankia 5y agoWhile I do know about those and they are indeed much more pythonic and cleaner, I often end up just using `lambda x: x[1]` instead of `import operator; operator.itemgetter(1)`. For sort, I'll also often do `sorted(mydict, key=mydict.get)` which is again not the most pythonic. I just wish there were nicer ways to do these in the global namespace, but poluting builtins is probably not a great idea either. Maybe `slice.itemgetter` or `object.attrgetter`.
- asicsp 5y agoSee also "Understanding all of Python, through its builtins" https://sadh.life/post/builtins/ https://sadh.life/post/builtins/
- efrank02 5y agopartial() is really useful and often overlooked
- teddyh 5y agoBut it’s not a builtin. partial() is in the functools module.
- alanwreath 5y agoI’m confused on this point, isn’t functools part of the standard library? Or has this changed?
- mixmastamyk 5y agoBuilt-ins are available without import. Stdlib are available without separate install.
- selcuka 5y ago> Built-ins are available without import. That distinction is a bit muddy: >>> import os >>> type(os.scandir) <class 'builtin_function_or_method'>
- idealmedtech 5y agoI'll probably get a lot of flak for this, but I find myself reaching for locals() a lot more than you'd think! It's great for prototyping, but also nice when you want to generalize things like filling a data class from kwargs, then an environment variable if that didn't work, then a config file if that didn't work, then a default if that didn't work. Probably not idiomatic, but reads simply enough and pretty bulletproof, especially considering the next easiest way is something quite dangerous like eval(). Happy to be proven wrong and learn something though!
- whalesalad 5y agoI don’t necessarily want to encourage this behavior but at the same time if it works and is “pretty bulletproof” in your deployments than I’d say more power to you.
- mixmastamyk 5y agoNone of those sound like use cases for locals. Why not *kwargs for the first example?
- eesmith 5y agoCan't set default arguments with kwargs. See my example at https://news.ycombinator.com/item?id=30623987 https://news.ycombinator.com/item?id=30623987 .
- saila 5y agoI personally wouldn't let any usage of locals() through code review, except perhaps in some extremely rare circumstance. Do you have an example of "filling a data class from kwargs"?
- musingsole 5y agoConcretely, why?
- idealmedtech 5y agoA dataclass is just a class where all it does is fill internal attributes (lots of self.x = "foo"). To fill a dataclass from kwargs, instead of: def __init__(self, x=None, y=None): self.x = x self.y = y You can do: def __init__(self, **kwargs): self.__dict__.update(kwargs) # This may be **kwargs, I'm fuzzy on it With this, the following code works with both: myObj = MyClass(x=1, y=2) Now, you might say "but with the kwargs method you can add _ANY_ attribute not just x and y!" That's precisely the point. When you're still iterating on the ergonomics, you want the ability to add new things without repeating a bunch of boilerplate. Once you've figured out what those look like, you can and should go back and fix the names in stone.
- MPSimmons 5y agoI very recently learned about dict().setdefault() For instance: def myfunc(**kwargs): # we need to be sure kwargs has ['foo'] set, with 'bar' as the default: kwargs['foo'] = kwargs.get('foo', 'bar') We could write that this way: def myfunc(**kwargs): kwargs.setdefault('foo', 'bar')
- wodenokoto 5y agoFor this particular use case, shouldn’t you just set the default value in the function definition or am I missing something? Def myfunc(foo=“Bar”): pass
- amelius 5y agoYou can't use this if you also have a nonlocal or global variable named foo that you want to access. foo = 123 def myfunc(foo="bar"): global foo # problem!
- diarrhea 5y agoThe main 'problem' there is the `global` keyword :^) (it's not needed for read access)
- amelius 5y agoHow would you read foo if it is hidden by a local parameter.
- diarrhea 5y agoI guess not at all. It's shadowed. But this being Python, this is a way: foo = 123 def lol(foo="bar"): print(globals()["foo"], foo) That will output "123 bar". But it's terrible! Your example is a SyntaxError, it doesn't even compile: In [1]: def myfunc(foo="bar"): ...: global foo Input In [1] global foo ^ SyntaxError: name 'foo' is parameter and global
- heavyset_go 5y agoI wish `any()` returned the first truthy item in an iterable instead of `True`.
- mixmastamyk 5y agoSounds like coalesce () from SQL.
- dragonwriter 5y agoSimilar, though a more perfect analog to coalesce() would return the first non-None item.
- pyuser583 5y agoI like.
- JNRowe 5y agoThe itertools documentation¹ include a recipe to do just that, and links to the excellent more-itertools² package which bundles up a heap of recipes that make iterators even better. This specific case is handled by first_true² in more-itertools. ¹ https://docs.python.org/3/library/itertools.html#itertools-recipes https://docs.python.org/3/library/itertools.html#itertools-r... ² https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.first_true https://more-itertools.readthedocs.io/en/stable/api.html#mor...
- memco 5y agoI think the first_true optio is great and I highly recommend more-itertools, but if you’re looking for a built in alternative I usually use next((I for I in iter if is_thing(I)), default) It’s slightly more work than any but is pretty much all I need when I need to handle whatever values are returned from the any.
- deleted 5y ago[deleted]
- deleted 5y ago
- tony-allan 5y agoGetting a bit off topic but useful. Input with history and editing: import readline while True: print(input('text>')) https://docs.python.org/3.8/library/readline.html https://docs.python.org/3.8/library/readline.html
- milliams 5y agoThat's really cool. I knew that Python had the `readline` module, but didn't know that it monkey-patched the `input` function to add functionality automatically.
- wodenokoto 5y agoI love these kind of “programming life hacks”, but I feel like Python is full of articles about “did you know you could …” which I don’t see so much for other languages. Since I work in data science I would love to read more “how to solve typical problems elegantly using base …” for both R and Julia. Is it a community or language thing? E.g, Python comes with more tools to do clever solutions, or is it something else? (Obviously the large user base helps)
- pletnes 5y agoPython’s user base is growing more each year than many other languages’ total user base. I’d guess more people will start learning python this month, than the total number of fortran, cobol, and lisp programmers ever lived. People who don’t even identify as programmers use python. It’s just a different world from most languages in this respect. (Although R probably has a lot of users in this category doing various data analysis.)
- smcl 5y agoAny other .NET folks out there that have accidentally misused the any() builtin when doing something in Python? About 2-3 times (with gaps of a year or so) I have accidentally used Python's any(some_collection) ("is there any element of some_collection that is truthy") where in .NET I would use someCollection.Any() ("is someCollection non-empty").
- clappski 5y agoWouldn't `Count` ( https://docs.microsoft.com/en-us/dotnet/api/system.collections.icollection.count?view=net-6.0#system-collections-icollection-count https://docs.microsoft.com/en-us/dotnet/api/system.collectio... ) be the preferred way to check if a collection has values? `someCollection.Any()` is the same as Python's `any`
- smcl 5y agoI didn't mean specifically ICollection, maybe I just used the wrong word (probably "enumerable" or "sequence" is better?). But I was referring to this method: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=net-6.0 https://docs.microsoft.com/en-us/dotnet/api/system.linq.enum... > Determines whether any element of a sequence exists or satisfies a condition.
- numeri 5y agoI'm extremely surprised to see `chr` and `ord` in the "You likely don't need these" section, and that the author has "never really found a use for them in [his] code". I guess he's never done any reverse engineering or NLP work?
- eesmith 5y ago... sure. But most Python programmers don't do reverse engineering or NLP work either.
- diarrhea 5y agoI've worked with Unicode and ASCII conversion directly before in Python, and even then I didn't need these two. There is `str.translate` which requires ordinals aka Unicode codepoints integers, which you would use `ord(str)` for. But then there's also `str.maketrans` which does this 'low-level' fiddling for you: https://docs.python.org/3/library/stdtypes.html#str.maketrans https://docs.python.org/3/library/stdtypes.html#str.maketran... . So even then, arguably a prime use case for `ord` and `chr`, I was able to forego them and work a 'level higher'.
- joppy 5y agoI guess the author has never done any (two extremely specific subfields) work? Most people don’t need to convert characters into numbers, there’s nothing overly surprising about that…