I'm not sure why you wouldn't just use packing to pass in a list of some objects that you need iterate over? Isn't it normally bad form to pass lists as arguments? I feel like I've read this somewhere but can't cite it
Python
Welcome to the Python community on the programming.dev Lemmy instance!
π Events
Past
November 2023
- PyCon Ireland 2023, 11-12th
- PyData Tel Aviv 2023 14th
October 2023
- PyConES Canarias 2023, 6-8th
- DjangoCon US 2023, 16-20th (!django π¬)
July 2023
- PyDelhi Meetup, 2nd
- PyCon Israel, 4-5th
- DFW Pythoneers, 6th
- Django Girls Abraka, 6-7th
- SciPy 2023 10-16th, Austin
- IndyPy, 11th
- Leipzig Python User Group, 11th
- Austin Python, 12th
- EuroPython 2023, 17-23rd
- Austin Python: Evening of Coding, 18th
- PyHEP.dev 2023 - "Python in HEP" Developer's Workshop, 25th
August 2023
- PyLadies Dublin, 15th
- EuroSciPy 2023, 14-18th
September 2023
- PyData Amsterdam, 14-16th
- PyCon UK, 22nd - 25th
π Python project:
- Python
- Documentation
- News & Blog
- Python Planet blog aggregator
π Python Community:
- #python IRC for general questions
- #python-dev IRC for CPython developers
- PySlackers Slack channel
- Python Discord server
- Python Weekly newsletters
- Mailing lists
- Forum
β¨ Python Ecosystem:
π Fediverse
Communities
- #python on Mastodon
- c/django on programming.dev
- c/pythorhead on lemmy.dbzer0.com
Projects
- PythΓΆrhead: a Python library for interacting with Lemmy
- Plemmy: a Python package for accessing the Lemmy API
- pylemmy pylemmy enables simple access to Lemmy's API with Python
- mastodon.py, a Python wrapper for the Mastodon API
Feeds
Look at the official docs. There is a table part way down stating which methods are available for each. I pick the one closest to how I use it. So if I'm not mutating I'll use Sequence over List to inform the caller I'm treating as immutable and to safe guard myself from mutating it in my implementation via static type analysis.
str
matches most of these contracts, though, requiring additional checks if a str
was passed or one of these collections containing strings.
Iβm rusty on my type hints because Iβve been living in lua land lately, but from ye olde PEP 20
Explicit is better than implicit.
Iβd combine them so the hint was something like Union[Collection[str], str]
But what if you actually don't want str
to be valid?
If you're writing code that generic, why wouldn't you want str
to be passed in? For example, Counter('hello')
is perfectly valid and useful. OTOH, average_length('hello')
would always be 1
and not be useful. OTOOH, maybe there's a valid reason for someone to do that. If I've got a list of items of various types and want to find the highest average length, I'd want to do max(map(average_length, items))
and not have that blow up just because there's a string in there that I know will have an average length of 1
.
So this all depends on the specifics of the function you're writing at the time. If you're really sure that someone shouldn't be passing in a str
, I'd probably raise a ValueError
or a warning, but only if you're really sure. For the most part, I'd just use appropriate type hints and embrace the phrase "we're all consenting adults here".
Maybe something like passing in a list of patterns which should match some data, or a list of files/urls to download would be examples of where I would like to be generic, but taking in a string would be bad.
But the real solution be to convert it to foo(*args: str)
. But maybe if you take 2 Container[str]
as input so you can't use *args
. But no real world example comes to mind.
A function that infinitely yields strings can be an Iterable without being a collection. You can create collections you can't irritate over by implementing only certain functions.
They both require different dunder methods.
I know that Iterable
and Collection
aren't the same. My point is, that if you use Iterable[str]
or Collection[str]
as a more flexible alternative to list[str]
you no longer have any type-hinting support protecting against passing in a plain string and you could end up with a subtle bug by unexpectedly looping over ['f', 'o', 'o']
instead of ['foo']
.
I'd leave a docstring:
def foo(bor: Iterable[str]) -> None:
"""foos bars by doing x and y to each bar"""
Type hinting isn't intended to prevent all classes of errors, it's intended to provide documentation to the caller. Iterable[str]
provides that documentation, and a docstring gives additional context if needed. If you want strict typing assurances, Python probably isn't the tool you're looking for.
This + an assert seems like the way to go. I think that str
should never have fulfilled these contracts in the first place and should have a .chars
property that returns a list of one-character-strings.
But this change would break existing code, so it is not going to happen.
IDK, I think strings being simple lists is less surprising than having a unique type. Most other languages model them that way, and it's nice to be able to use regular list actions to interact with them.
It's really not something I'm likely to run into in practice. The only practical way I see messing this up is with untrusted inputs, but I sanitize those anyway.
Kids these days and their type hinting. Back in my day, all objects were ducks, and we liked it!
π¦