"All Code Sucks" is a lot of fun! One-liners are so tempting. There's always that itch inside to make the solution fancy and perfect and smart, but maybe writing simple and straightforward code is better after all. :D
Yes I agree 100% about one liners. If you find yourself writing a one liner often, abstract it to a function and name it accordingly so it “reads” easier to the other developers. Something as simple as inline sorting logic can be extracted to a named function to make it even clearer (i.e. sort_by_page_title_descending() ) Tangentially, I’m of the camp that the longer the variable names are, the better documented and easier to read your codebase is. Definitely not a 1to1 but it’s always a good sign.
Go has context and defer for example. I've never seen a valid use case for ExitStack. Just write proper code in the first place and don't wrap it in some conditionally closed context.
@@vasiliigulevich9202 Huh? It runs all exit callbacks when you exit the scope. Are you talking about something else? In any case, that does not sound like a place where you would want to combine several context managers into a single with statement..
@QckSGaming yes, but the scope is not limited to a method or a with keyword. Asking ExitStack to na member and manage lifetimes of other members or dependencies. I usually implement C++ RAII with it by disposing all members together with their container. But it is a bit more flexible than just that.
The number of times I've seen or left PR comments to the tune of: "This is some clever code. Can't find the bug, but I know it's there somewhere" is more than one. That's too many. xD
10 วันที่ผ่านมา +8
For a simple case like this, I think I would use "context = open(file) if file else contextlib.nullcontext(sys.stdin)"
how about file, cm = (file, open) if file else (sys.stdin, nullcontext) with cm(file) as stream: return next(iter(stream)) handles the cases anthony uses in the vid
surprised to hear about perpetual issue of conditional contexts - isn't this what nullcontext is for? i've used it successfully to conditionally manage seek-offsets and temporary-filters for db cursor management. smth like this? i dont like doing two checks for file=None, but maybe there's another implementation and in any case definitely think nullcontext should be mentioned! import sys from contextlib import nullcontext def read_first(file: str | None = None) -> str: cm = open if file is not None else nullcontext with cm(file) as stream: stream = stream or sys.stdin return next(iter(stream)) edit: def read_first(file: str = None) -> str: file, cm = (file, open) if file else (sys.stdin, nullcontext) with cm(file) as stream: return next(iter(stream))
You lose the ability to specify different parameters if you simply use nullcontext() What Anthony showed is a generalized solution. Sure you can use functools.partial() but that adds too much "cleverness" to the code.
I don’t think a lot of people would understand why the new code is written that specific way, I rather do the if outside and conditionally enter the context with a plainer looking code and 2 duplicate returns
Define a function that works on pre-opened file descriptors and manage opening outside? Why switch between very different and fragilely stateful types - I mean it's simple for me to say that once I see the important difference between the two :)
"All Code Sucks" is a lot of fun!
One-liners are so tempting. There's always that itch inside to make the solution fancy and perfect and smart, but maybe writing simple and straightforward code is better after all. :D
Yes I agree 100% about one liners. If you find yourself writing a one liner often, abstract it to a function and name it accordingly so it “reads” easier to the other developers. Something as simple as inline sorting logic can be extracted to a named function to make it even clearer (i.e. sort_by_page_title_descending() )
Tangentially, I’m of the camp that the longer the variable names are, the better documented and easier to read your codebase is. Definitely not a 1to1 but it’s always a good sign.
"it's still in production" industry standards bite again
ExitStack is magic. I'm yet to encounter something so elegant in any of the few languages that I write alongside Python--TS, Go, Elixir, etc.
It is RAII concept from C++ and Ada. Python and Java use libraries to achieve the effect.
Go has context and defer for example. I've never seen a valid use case for ExitStack. Just write proper code in the first place and don't wrap it in some conditionally closed context.
@QckSGaming it is needed to track out-of-stack lifetimes. For example a log-lived socket connection that can't be closed after method returns.
@@vasiliigulevich9202 Huh? It runs all exit callbacks when you exit the scope. Are you talking about something else? In any case, that does not sound like a place where you would want to combine several context managers into a single with statement..
@QckSGaming yes, but the scope is not limited to a method or a with keyword. Asking ExitStack to na member and manage lifetimes of other members or dependencies. I usually implement C++ RAII with it by disposing all members together with their container. But it is a bit more flexible than just that.
The number of times I've seen or left PR comments to the tune of: "This is some clever code. Can't find the bug, but I know it's there somewhere" is more than one. That's too many. xD
For a simple case like this, I think I would use "context = open(file) if file else contextlib.nullcontext(sys.stdin)"
would this properly close the file?
@ArielVolovik Yes, but there's a chance the process terminates between the `open` and the place where you use the context
how about
file, cm = (file, open) if file else (sys.stdin, nullcontext)
with cm(file) as stream:
return next(iter(stream))
handles the cases anthony uses in the vid
@@prosodyspeaks4036What if you want to specify parameters to the open() call?
Anthony, you are the best. Please keep up with such content!
Very clever, thanks for sharing
surprised to hear about perpetual issue of conditional contexts - isn't this what nullcontext is for?
i've used it successfully to conditionally manage seek-offsets and temporary-filters for db cursor management.
smth like this? i dont like doing two checks for file=None, but maybe there's another implementation and in any case definitely think nullcontext should be mentioned!
import sys
from contextlib import nullcontext
def read_first(file: str | None = None) -> str:
cm = open if file is not None else nullcontext
with cm(file) as stream:
stream = stream or sys.stdin
return next(iter(stream))
edit:
def read_first(file: str = None) -> str:
file, cm = (file, open) if file else (sys.stdin, nullcontext)
with cm(file) as stream:
return next(iter(stream))
You lose the ability to specify different parameters if you simply use nullcontext()
What Anthony showed is a generalized solution.
Sure you can use functools.partial() but that adds too much "cleverness" to the code.
That's a dirty bug!
I don’t think a lot of people would understand why the new code is written that specific way, I rather do the if outside and conditionally enter the context with a plainer looking code and 2 duplicate returns
That's why code comments is important.
Just describe the "why" to prevent others from doing the same one-liner mistake.
One of the only in python videos 😂
Define a function that works on pre-opened file descriptors and manage opening outside? Why switch between very different and fragilely stateful types - I mean it's simple for me to say that once I see the important difference between the two :)
ohh neat trick