#internals-and-peps
1 messages · Page 36 of 1
:white_check_mark: Your 3.14 eval job has completed with return code 0.
(1, 2, 3)
though I doubt that behavior is guaranteed by the language. That code might behave differently on other Python implementations, or even future versions of CPython.
That would be bad if it does change
well, I'd be interested in a core dev's opinion on whether that's a language guarantee or an implementation detail 🙂
If it's not part of the interface, it should have a dunder name, should it not?
It could be part of the interface but whether it's set in __new__ or __init__ could be an implementation detail.
that, and also I think you mean sunder, not dunder. dunders are definitely part of the interface.
And this is probably code that Guido wrote 30 years ago.
I did mean dunder. Unspecified dunder names are still reserved for internal use
that just means that new dunders may be added to future versions of the language, right?
I thought they could still use used for non-public implementation details
I don't see why you'd choose to use a dunder for that instead of a sunder. dunders are specifically for protocols - the whole point of dunders is that something else is gonna call them
If it's part of the language or the standard library it's going to be documented somewhere.
I just thought cpython had unspecified dunders that were basically sunders but only for cpython itself 
sunders aren't really a thing IMO. They're a convention for library code to say "this thing should be kinda dunder-like but doesn't actually have any special syntax support, it's just that we have to make the name special for some reason"
(for example, because it's supposed to be possible to attach "arbitrarily" named attributes, like with dataclasses and namedtuples and such)
and I feel like only the core dev team should really be defining semantics for dunders
Should i post this on discourse python website to get more reach and Attention of core devs?

Not meaning to spam or disturb core devs
posting a question on discourse isn’t spamming
it’s be spamming if you ask and then re-ask though
as a core dev my opinion is that you don't need to be a core dev to have a good answer to these questions
That seems like the kind of thing we can't realistically change, it would break way too much code
Thanks Jelle & ngoldbaum! I will soon post on discourse.
This was confusing but I guess it makes sense: https://github.com/python/cpython/issues/148316
Bug report Bug description: You can reproduce this by installing 3.15.0a8, creating a venv that includes the asv package, and doing asv run in the root of this test repository: https://github.com/n...
too bad adding stuff to the standard library breaks ecosystem packages
I hadn't realised that adding colour to argparse had lead to argparse importing dataclasses and as such getting hit with the import penalty of dataclasses I'd otherwise been working hard to avoid.
I already have one work-around to prevent it from importing shutil unnecessarily to work out terminal width
what happens if I do token lookahead
#define LOOKAHEAD1(NAME, RES_TYPE) \
int \
NAME (int positive, RES_TYPE (func)(Parser *), Parser *p) \
{ \
int mark = p->mark; \
void *res = func(p); \
p->mark = mark; \
return (res != NULL) == positive; \
}
LOOKAHEAD1(_PyPegen_lookahead, void *)
until the tokenizer passes to a new line and updates tok->linestart. If I then request a token _PyPegen_fill_token, tok->line_start wont be restored.
Hello @tidal token, I've deleted your message. I don't believe we can help you with it, doing it would be illegal if I understand it correctly. In addition, it's also off-topic for this channel.
It's not something illegal, just in Iran, which the goverment is managed by a terrorist regime
I'm talking about sanction-evasion laws outside Iran. Either way it's off-topic for this channel, we can about it in an off-topic channel like #ot0-psvm’s-eternal-disapproval
So I've been using it as an example in discussion on an @ syntax for Annotated (not in favour) but I was wondering if it's worth changing the __repr__ of ForwardRef for unions to show the type_repr of object names instead of showing the internal names.
I haven't heard about this--is there a PEP?
It's just a discussion on dpo, not at pep stage
do you have the link?
But I'm talking about this
>>> from annotationlib import get_annotations, Format
>>> class Example:
... a: ref | str
...
>>> get_annotations(Example, format=Format.FORWARDREF)['a']
ForwardRef('ref | __annotationlib_name_1__', is_class=True, owner=<class '__main__.Example'>)
The names are needed internally, but I think it would be nicer to not show them to users. I've been experimenting with this in my reannotate library when given a ForwardRef as the source for a deferred annotation and I think we could do something similar for ForwardRef.
>>> from reannotate import DeferredAnnotation
>>> anno = get_annotations(Example, format=Format.FORWARDREF)['a']
>>> anno
ForwardRef('ref | __annotationlib_name_1__', is_class=True, owner=<class '__main__.Example'>)
>>> DeferredAnnotation(anno)
DeferredAnnotation('ref | str')
I was unsure if this would be considered a bug, but the names do also 'leak' for .evaluate(format=Format.STRING) so maybe?
Yes, I think that would be nice to improve
!clban 631391575674585089 some kind of scam
:incoming_envelope: :ok_hand: applied ban to @wind jolt permanently.
!warn 1476993310399791145 stop spamming
:incoming_envelope: :ok_hand: applied warning to @verbal gate.
I don't see how that's related to Python internals?
@sharp furnace I removed your message as it isn't related to the channel, but you can post it in #1468524576479641744 if it meets the requirements given in the pinned thread there.
Huh, dataclasses has some special case handling for when it has no methods to generate, but it then still execs and calls an empty __create_fn__ method generating function.
bug? Though I wonder what the use is of dataclasses when it doesn't create any methods
Well it works, but it's calling a function that returns an empty tuple and then does nothing with it because there are no names.
The use would be wanting dataclasses to do all of the internal stuff, but replacing all of the methods
what is the internal stuff? just creating the __dataclass_fields__ dict?
also potentially slots
I guess it's at least an easy performance optimization, we should fix it on main
It's somewhat related to the _colorize performance issue, I was investigating replacing all of the execed methods with regular dynamic ones. Outside of imports the module spends most of its time execing dataclass methods.
is it normal to have your repo name and source folder be the same?
yes. some people will nest the source folder in a src/ directory
yes that would be nice! exec() is quite slow and maybe there's a more performant way to get the same behavior
Brandt did some experiments in the past to cache things more, but we didn't end up landing that
Well this is more specific to _colorize. In this case the methods themselves would be slower and dynamic, but it doesn't matter much as they're not heavily used (or not used at all).
I have a classbuilder like dataclasses which instead generates the methods when used. You don't avoid the exec() penalty completely, but do for methods that you want to have but don't actually use.
(Like the __setattr__ and __delattr__ on frozen dataclasses, which in most cases should never get touched)
!compban 1483490818735210607
:incoming_envelope: :ok_hand: applied ban to @coral turtle until <t:1777064424:f> (4 days).
In [48]: defaultdict[str, list[int]]
Out[48]: collections.defaultdict[str, list[int]]
In [51]: defaultdict[str, list[int]]()
Out[51]: defaultdict(None, {})
Is there any way this could be made smart enough that defaultdict[X, Y[Z]]() evaluates to defaultdict(Y, {})?
so that you don't have to do defaultdict[X, Y[Z]](Y)
There's always a way. If you make defaultdict.__orig_class__ a descriptor that when set mutates the defaultdict's defaultfactory, you can do it
this is not advisable
I think Stel is asking if this could be added to the language/collections
thanks for your response, but I'm not sure what you mean. defaultdict[str, list[int]]() doesn't evaluate to defaultdict(list, {}) even though it's ostensibly inferable that list is the default factory.
I'm saying this is how it could be implemented. It doesn't work that way today.
I'm not sure it generalises. Also it would make more sense to me for it to evaluate to defaultdict(list[int], {}) if it did.
Guess the first code every python developer should know
Print("hello, world")
I see. Why is it not advisable?
The specific mechanism I suggested is very hacky. And as David points out it doesn't easily generalize to all types, like what if you had a defaultdict[str, Literal[1, 2, 3]]?
Possibly something like this could be made to work, but it would require parsing type annotations in C
it would also be a breaking change
You could subclass defaultdict and define __class_getitem__ to implement it on that subclass.
it would be cool to be able to write defaultdict[str, _](list[int]) similar ot Rust
where _ is deduced automatically, but str cannot be deduced automatically
I feel like that would be more confusing in the python context given how these things 'normally' work.
better yet, avoid defaultdict entirely and use dict.setdefault as needed 😛
no better way to get quicknir to show up than to talk about defaultdict 😛
maybe I should learn how to write a discord bot and automate myself 😂
!warn @shrewd terrace you need to stop advertising your AI-generated AI learning website.
:incoming_envelope: :ok_hand: applied warning to @shrewd terrace.
!compban 1495168519870877868
:incoming_envelope: :ok_hand: applied ban to @buoyant summit until <t:1777316021:f> (4 days).
Hi all, I'm new to contributing to cpython (other than opening issues). Last week I went down the rabbit hole of improving re.search performance for some use cases, and I made two PRs. The first of them is trivial: make "^foo" fast-forward to the next newline, which is often 10x faster (https://github.com/python/cpython/issues/148762). The other has more nuanced results: using memchr instead of a handwritten loop to fast-forward to the next possible match of "foo"; it's very fast if the first char is rare, but slow if dense in the string (https://github.com/python/cpython/issues/148729). Wondering if I can nerd-snipe someone here and wanted to start a discussion what use cases re.search should be optimized for.
A little suggestion, I’d wait for maintainer feedback on one of the optimisations before opening more.
I wonder how people who have a lint against shadowing builtins will cope with adding new built-in names
I guess it's a very rare occasion
lots of # noqa I would imagine
!pep 661
yay
I'm on a walk right now, but it looks like the tldr is that you can use what is essentialy the object-sentinel pattern in a way that won't upset linters?
Also a better repr and picklability
I strongly dislike the customization fo __bool__ and __repr__ but whatever
Glad it's finally in, I've been watching that discussion for a few years now it seems
__bool__ isn't mentioned, it's always truthy
I mean I live without the repr
this will be nice for NumPy in a few places
we have a singleton that represents a default argument that’s not None
for example
They don't let us pick the truthyness by not giving an option for __bool__. It will just always be True unlike how we may want inverted like it is for None
I'm surprised that one was rejected. Seems very useful
I think truthiness in general is a gateway to bugs like this py def compute_something(names=None): names = names or ["<default>"] # uninentional override when names == [] ... and it also mimics _a_sentinel = object() which is a very popular "vanilla" sentinel idiom (if you don't need type checking support), and the enum-with-single-item idiom
but I am also a truthiness hater, so I am biased
I'm wondering if the typing aspect was the complexity
Mentioned complexity for rejection, I mean
and this is how I learn about it 😄
sorry, did I spoil the surprise 😅
that's a really cool pep
And renaming: https://github.com/airspeed-velocity/asv/issues/1584
I have a fun case of two sentinels where one is due to None being a valid value and the other is due to the first sentinel being a valid value
It's a dataclass-like where the equivalent of dataclasses.Field is essentially also a dataclass
this is like in a physics class when they run out of greek letters and start using random other symbols
It's kind of the case that for this bootstrapped field default=MISSING needs to indicate that the default value is actually the value MISSING and not that there's no value.
But that means it needs a new value to represent actually missing
@feral island are you planning to also publish a backport package for PEP 661 after beta1?
it's already in typing-extensions
I think NumPy already even depends on that
(though with slightly different behaviors, I'll update that to the extent typing-extensions's own BC allows)
maybe it makes sense to publish backports.sentinels with exactly the same behaviors? if that matters at all.
feels like overkill
differences are:
typing_extensions.Sentinelis subclassable- it accepts an extra
repr=argument, and the defaultrepris different - it's not picklable
I wonder why it's called sentinel and not Sentinel? Because it's in built-ins?
yes
I might see if we can replace np._NoValue with the typing_extensions implementation today.
oh the typing-extensions version is also weakrefable
I guess I can read the PEP, but are the 3.15 sentinels immortal?
no
I guess there’s always the unstable SetImmortal C API as an escape hatch if that ever matters for performance
yes. this didn't come up during the discussion and I hadn't thought about it
but yeah the existing SetImmortal should be enough
With this and lazy imports I already want to drop support for 3.14 and earlier in projects 😂
you don’t really notice reference count churn much except on the free-threaded build when it introduces contention, I expect making things immortal will come up more as more people use the free-threaded build. The thought of publishing a package that ships wheels and exposes a Python API for PyUnstable_SetImmortal has occurred to me.
ctypes? 😄
I can tell you from my own experience with PEP 797 that immortalizing GC-tracked objects is extremely difficult to do safely
I would just enable deferred refcounting on sentinels if it becomes an issue
I’ll try to keep that advice in my back pocket. I want to add more profiling and performance tuning advice to the free-threaded guide. I also should play with tachyon finally.
opened https://github.com/python/typing_extensions/issues/742 about updating the typing-extensions version
Thanks. The first PR got approved within a day (but maybe not by a core cpython member?), and the second PR is similar but sufficiently different. That's about a 9-10x performance improvement (https://github.com/python/cpython/issues/148762) for matching re.compile("^foo", re.MULTILINE) and is almost trivial and very similar to an existing optimization. Would be nice to discuss re performance with someone.
i have a question. ptr seems like it points to the start of the string/string slice, so isn't there a concern about doing ptr[-1]?
Why does typing-extensions provide the same compatibility guarantees for actual backports and for speculative things that might not even land in Python?
That seems a bit strange. I would put stuff that's not yet a backport into a separate namespace, like typing_extensions.nightly or typing_extensions.experimental. For example:
- PEP 999 proposing to add
Foois posted as draft andtyping-extensionsmaintainers decide that it's pretty cool typing_extensions.experimental.Foois added for type checker authors and people who want to play around with it.- once the PEP is finalized,
Foois removed from the experimental module - if PEP 999 is rejected, nothing else happens
- if PEP 999 is accepted as is,
Foois just moved totyping_extensions - if PEP 999 is accepted with changes, the changed
Foois added totyping_extensions
I'm sorry I can't help there, it's not my area of expertise, re is looked after by Serhiy IIRC. The general advice (which I don't think we've actually noted in the devguide) is to open an issue and wait for maintainer feedback before opening a PR.
Heh, yes, it was missing ptr > state->beginning, I'll stay away from mentioning "trivial" next time. And @deep dirge, good to know. I've closed both PRs to reduce the noise and left the issues open; the suggested patch fits in the issue anyway.
In [37]: text = "Data science is fun. Data science is powerful. Data!"
In [38]: sorted(re.findall(r"\w+", text.lower()))
Out[38]: ['data', 'data', 'data', 'fun', 'is', 'is', 'powerful', 'science', 'science']
In [39]: Counter(sorted(re.findall(r"\w+", text.lower())))
Out[39]: Counter({'data': 3, 'is': 2, 'science': 2, 'fun': 1, 'powerful': 1})
In [40]: Counter(sorted(re.findall(r"\w+", text.lower()))).keys()
# The order of the keys changes!
Out[40]: dict_keys(['data', 'fun', 'is', 'powerful', 'science'])
In [41]: sys.version
Out[41]: '3.12.9 (main, Mar 17 2025, 21:01:58) [Clang 20.1.0 ]'
doesn't this contradict specified behavior for dict iteration order?
looks like Counter.__str__ displays the KV pairs in descending order of (v, k), but that might be separate from its iteration order
The __repr__ uses Counter.most_common
>>> l
Counter({'data': 3, 'is': 2, 'science': 2, 'fun': 1, 'powerful': 1})
>>> l.most_common()
[('data', 3), ('is', 2), ('science', 2), ('fun', 1), ('powerful', 1)]
does anyone ever wish dict.setdefault could take a callable?
I don't see why it would need to (and also, it can take a callable, it's just not gonna call it)
Yeah I mean take a callable and only call it if the key does not exist. Its nice for placement of nested dictionaries. I know there's collections.defaultdict but its not as flexible
It cant be that uncommon
https://stackoverflow.com/questions/17532929/how-to-implement-a-lazy-setdefault
defaultdict just isn't a good because its for the entire dict whereas I may I want a different container per key
I see, only call it if the key doesn't exist. Because you could just call the function and pass it as the default
yeah I could do dict.setdefault(key, {}) but then im making a dict that may just get thrown out
it would be a little nicer, yes
and you do see this in other languages, fwiw
that said the cost of making a dict that potentially gets thrown out is negligible in like 99% of contexts
is __missing__ an option?
the other option is obviously to just write a function; not as nice as a member but on the flip side you can hardcode a dict as the default for example, for that use case
and since passing a lambda in python is also not super nice, it's a decent option
get_or_dict(my_dict, key)[...]
pytype/vm.py line 515
# I have no idea why we need to push the exception twice! See```
does anyone know the reason that we have to do this?
That's no different than defaultdict pre-set to 1 callable. dict.setdefault would present more flexibility at call site
one nice aspect of the current behavior is that it’s atomic, see the thread safety note in the C API doc: https://docs.python.org/3/c-api/dict.html#c.PyDict_SetDefaultRef
not that adding your feature would break that, it just couldn’t be atomic with a python callable involved
I think you'd need something like setdefaultfactory as a callable could itself be a valid value
Though I'd be surprised if you could write a version of that in Python that wasn't slower than creating and throwing out the unneeded dict
Maybe if the container is sufficiently slow to construct
if it's a meaningful amount of work / has side effects I'd even argue for desugaring the setdefault call into an if x not in y: block
I also miss that in Python. if x not in y: y[x] = <expression> hashes twice, which can be expensive, and y.setdefault(x, <expression>) evaluates eagerly, often leading to redundant allocations, defaultdict is too static for all use cases.
that note is for the key and not the value? The callable would be for the value portion
right, like i said, this can't be atomic with a python callable
dict.setdefault is a nice primitive for building thread-safe caches and you kinda want that property, but adding callables to that complicates things
hard to think of a safe way to do it without a lock
You mean the note from *PyDict_SetDefault?
Im probably asking stupid questions because I dont understand a lot of threading stuff
ideally you'd want what you're proposing to work like the c++ std::call_once
or rust’s OnceLock: https://doc.rust-lang.org/std/sync/struct.OnceLock.html
A synchronization primitive which can nominally be written to only once.
I've been investigating the cached code idea for dataclasses again by implementing it on my own classbuilder. It does seem to be fast if you have a lot of similarly-shaped functions which works well for things like __eq__ and __repr__.
It does however bring the temptation to add things like this: https://github.com/DavidCEllis/ducktools-classbuilder/blob/cached-source/src/ducktools/classbuilder/_cached_methods.py
!learn
Here are the top free resources we recommend for people who are new to programming:
- Automate the Boring Stuff — an online book (also available to purchase as a physical book)
- Harvard’s CS50P course — video lectures (slides and notes provided) with exercises
- Python Programming MOOC 2026 course — text-based lessons with exercises
- Corey Schafer's YouTube playlist
For a full, curated list of educational resources we recommend, please see our resources page!
is there a pep standard for this? having a disagreement with my coworker
don't think there is any standard for source layouts
it's recommended. i'm sure there's a strong opinion piece about it, but i can't find it at the moment.
the argument for the src/ layout is that it forces you to install the project before you can test it, which means your tests exercise the project as it gets installed, instead of as it exists in the source tree, and therefore they test the package build setup.
the argument against the src/ layout is that it forces you to install the project, and people who don't understand that try to work around it by doing from src import ... and making things worse and harder to clean up while working around the feature that the src/ layout is meant to give
I don't really like that it forces a mostly useless layer of extra directory
src/ is good for namespace packages
It's not useless, it serves a purpose: making it so that importing the module fails unless you've installed it the package
The whole point of the src/ layout is just to force maintainers to install the module before running the test suite. Whether having the extra directory is a worthwhile cost to be able to enforce this is a matter of opinion 🙂
The src/ layout is a low tech hack to work around the Python interpreter having bad defaults - importing random files from the current working directory might be what you want before you've learned to make packages, but it's certainly not what you want when trying to test a package
There are probably quite a few, this one is linked to from the pytest docs https://blog.ionelmc.ro/2014/05/25/python-packaging
Thoughts on packaging python libraries — Note This is about packaging libraries, not applications. ⸻ All the advice here is implemented in a project template (with full support for C...
I'd find this more convincing if src were an invalid package name. As Jelle says, I've seen so many examples of folks doing things like from src import foo or from ..src import foo because they just totally misunderstood what this convention was trying to guide them towards
yep, if you don't understand what it's for and how it's achieving that goal, it's easy to make things worse with it.
I used to think it was pointless, then i thought it was good, now (after maintaining a type checker for a bit and seeing the many ways in which folks misunderstand Python import conventions) I'm once again no longer convinced it's a net positive
If the convention was s-r-c or source-code it would be much more obvious that it's not meant to be importable
I'm not sure that'd stop people from doing export PYTHONPATH=source-code, but at least it'd stop from ..source-code import ...
i feel like most of the folks doing this kind of thing are just doing the first thing that works, and have never heard of PYTHONPATH
probably true. I think most of the from ..src import ... lines get written by IDEs or text editors trying to be helpful without understanding the src/ layout convention
Nowadays it might be agents doing the first thing that works, and i guess they've probably heard of PYTHONPATH... but I'd also expect them to understand the convention more fully out of the gate
I think there's plenty of arguments on both sides of it being good and bad, but I think whichever way anyone feels about it, the important thing to understand about the src/ layout is that it is a (low tech, hacky, easily subverted) way to work around Python's defaults doing something different than package maintainers need. Being able to run the tests or the entry points without installing the package is bad - the dependencies don't get installed, generated files might not be generated, things might not be in the right layout, you're not testing that your packaging configuration copies every file it's meant to, etc. Python putting $PWD on the path by default bit enough maintainers that the src/ layout naturally arose as a way to try to work around the maintainer-hostile default
Yes. I think it is almost certainly beneficial for experienced maintainers of projects who want to make sure they're actually testing what they want to test, etc. But it definitely has costs as well, especially for beginners (and even intermediate developers) who aren't up to date with the latest conventions and the motivations behind them
yeah. That's pretty much where I land on it at this point: I use it for my own projects, but I no longer recommend it to beginners
a strong opinion piece would be very helpful
if you happen to find one please let me know
thanks
there have been a few linked in this discussion.
I do actually find the import from working folder useful sometimes. I'd say the 'src' layout is fairly well established for actual projects at this point.
someone should give @meager nacelle a core role, they’re a CPython triager
me too I guess but I’m already purple
I'll ping the appropriate people
ooh sorry i see now!
ty!
ty!
Guys! PEP 810 is coming! 😭 I've been praying for this!
it's already here, no? 3.15.0a8
3.15 is finally out?!
Dude I stopped paying attention to Python for like... a year and I came back to this
Ok, I just checked. That's a pre-release. I don't touch it until it's a stable release.
right, a8 means the eighth alpha release.
Full releases in october
Ik I just checked. I don't want to wait that long 😭
3.15 has a ton of cool stuff in addition to lazy imports
i'm personally quite excited about sentinels and tachyon
oo, what's a tachyon?
let's try something
the hard way then 😔
(new to 3.15)
And don't forget about all the color! (See the very accurate statistics!)
Wait, there's a core role and triagers are eligible?
There is a triager role now, so you should probably have it too
I like the additional colour, but I'm a little torn on the addition to more modules right now due to the design of _colorize. Each new theme adds a new frozen dataclass and makes the module slower.
Couldn't the themes live in another module and be lazy imported?
I don't know, the whole design has one main class that then has an instance of each 'theme' dataclass as attributes
There's also some stuff that we're maintaining that could just be removed in there. I'm pretty sure copy_with is just __replace__ written by hand.
Yeah dataclasses ain't great. We also have an open issue for a benchmark if anyone's interested.
That would probably be a good thing to add in before making improvements to it to compare options.
That said I only really have synthetic benchmarks I've used to compare things, other than "how fast does _colorize import with these changes"
looks like this is fixed, thanks!
and you got the new role too!
It's all quite interesting I just saw news of the lazy imports and got excited. I read through it, I'm definitely excited for Sentinels so I can stop doing X: Int | None. I haven't read into Tachyon enough but the claims made sound very... iffy? I'd like to see it before I believe it. Finally moving to UTF-8 as standard encoding is a big win and the FrozenDict is cool but FrozenDict seems kind of niche. I'm definitely excited for the Free-threading updates
how would you use sentinels instead of X: Int | None (or did you mean int | None)?
I meant int | None I apologize, I'm shuffling back and forth between apps right now
Trying to get Wayland and XWayland to play nice
np, i figured, but I'm still not sure how a sentinel helps
IMO None should still be the default argument you use most of the time
builtin sentinels only help for situations where passing None is semantically meaningful and you need something else to represent nothing being passed in
and even then you can do it without the builtin support, it just adds boilerplate
tbh, i'm still a bit surprised that specialized sentinels are important enough to become a feature, including a word in builtins
I think if the alternative is _sentinel = object() it generally makes that nicer, and there are quite a few places where None ends up as valid or that it really just doesn't mean the right thing.
i should read the whole pep if i really want to know, but why couldn't this have been a pypi project? where is the stdlib using sentinel?
Dataclass fields
Few others too but they're interval iirc
do you have an example?
You need a sentinel to represent no default
It's like MISSING or something for the default
because None could be a valid default
hmm, ok, and why a builtin?
As a heavy user of Pydantic, the None(s) are very semantically meaningful
https://pydantic.dev/docs/validation/latest/concepts/serialization/#excluding-and-including-fields-based-on-their-value
Whether that requires a dedicated builtin, I don't care either way
But there does need to be something to seperate nothing given vs user explicitly wants None
My implementation is here
https://github.com/impressdesigns/onsite-edp-sdk/blob/main/src/onsite_edp_sdk/models.py#L310-L318
I have never used over half the available fields
I need them to stay out of the output
dataclasses.field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=MISSING, doc=None)
More arguable, it does mean that it can essentially be used everywhere where they are needed
an import would allow that also
do we think we need more sentinel than Callable or Any?
Personally I wouldn't be fussed over a new import but I would over a new slow import. There was the issue of a pre-existing package called sentinels?
If I had to import typing for it I couldn't use it (with typing as it is now)
Those are a bit different bc their lower case versions are existing builtins and they're for typing only
i shouldn't second-guess the PEP.
I do wish they didn't have to be imported though, it's annoying to do it on so many files
I really don't mind the extra line for import, it's the import time that bugs me
@spark magnet if you just want the rationale for the builtin - https://peps.python.org/pep-0661/#use-a-new-standard-library-module
" The Steering Council also specifically encouraged making the feature a builtin so that it is at least as easy to use as object()." This seems like a very weak reason, but a builtin isn't such a bad thing anyway, as long as my linter doesn't complain about it
It probably will for a bit
Was there ever a proposal to special-case more built-in names in a typing context? E.g. make callable and any behave like typing.Callable and typing.Any.
One thing I will like is the typing fix it gives where you have to use them
It's been brought up before
not sure what the resolution was or where so I'm not very helpful here though 🤔
But it will be nice to not have type checkers complain that an object could be some other instance of _SentinelType
(And if cheeky could also add iter[foo] as a short-hand for Iterable[foo].)
i'm still not sure about my original question: how would you use sentinel to help with x: int | None?
You don't really? I'm not sure how it was supposed to help there either.
I want it to help with:
thing: int | SentinelType = get_thing()
if thing is not Sentinel:
# type checker still thinks it can be SentinelType
# because it may theoretically be a different instance
...
It would require making functions subscriptable
And there's a pep from @feral island for that ? Which may clash
Cuz jelle's is for generics
probably butchering that
We're going to make it so sentinels can be used directly in types (like None today), though type checkers still have to implement that
There's an active PEP (718) for subscripting functions, it's not mine and I don't see how it relates to sentinels
Sorry I meant to reply to this one
Making callable double as Callable
I think somebody already linked my page explaining the problems with that idea
Ah I didn't scroll
I should read more about how __class_getitem__ is supposed to work with typing. Right now the numpy dtype class has an implementation that exists for typing purposes but I also think it would be neat if it worked at runtime
so np.dtype[np.int64] returned the dtype type at runtime
generally they just literally return types.GenericAlias(origin, args)
yeah that’s how it works, but that’s not terribly useful for anyone doing anything at runtime
it's not? what would you want instead?
an actual instance of the dtype type, what you’d get from np.dtype(np.int64) instead. I guess it doesn’t make much difference though, just parens and brackets
ayooo i’m scarlett, first of all, i want to say that i’m TERRIBLE at computers, and I'm really interested in learning, it doesn't matter what it is, i honestly want to learn everything, although i’m a little more interested in coding and programming 😭 but idk how to start
head over to #python-discussion for help with it
I think maybe worth mentioning that a broad class of situations where you can't really use None as a default is in generic code
if you're in principle taking an int or str then None is a fine default to indicate absence but in almost all situations where you're taking a T it's not really okay to use None as a default
One place you see this is in the standard library btw; it's a bit of a niche case but it means that API like dict.get (the one argument form) is not really useful in some situations because you lose the ability to tell if a key was absent, or present and mapping to None
Kotlin has the same issue; any language where the "None" situation is such that there isn't really nesting has a tendency to run into this
where is the stdlib using sentinel?
Victor came up with a list of places where the stdlib uses sentinel values. https://mail.python.org/archives/list/python-dev@python.org/message/JBYXQH3NV3YBF7P2HLHB5CD6V3GVTY55/
that's linked from https://peps.python.org/pep-0661/
Some more linked via https://github.com/python/cpython/issues/149083
Feature or enhancement Proposal: I just merged support for PEP-661, which adds the new sentinel() builtin. Let's use it in the standard library so we can simplify some code and stress-test the ...
which I guess mostly missed the boat for 3.15, oh well
but we got a few:
$ ./python.exe
Python 3.15.0b1+ (heads/3.15:e81025e6d2e, May 7 2026, 10:29:46) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import typing
>>> type(typing.NoExtraItems)
<class 'sentinel'>
>>> import dataclasses
>>> type(dataclasses.KW_ONLY)
<class 'sentinel'>
Well, we have to save something for 3.16
The stdlib advantage of being able to use the new features immediately
It's the other way around, isn't it? If something can be released as a PyPI package, people can start using it immediately. If it's released as part of the stdlib, people need to wait until the minimum Python version they support has the feature in its stdlib
but in the stdlib, we can use it immediately
for sentinel specifically, third-party users can also use it already via typing_extensions.Sentinel
Advantage for the stdlib, not for the users of the stdlib
Yes I meant that the stdlib can immediately use new language features, while outside of it you have to wait to use them until you don't need to support python versions without the features
Which is useful because it gives us some immediate usability feedback for new features
Yes it's definitely useful to be able to do it inside of the stdlib and good to do so
But I want to drop all my lazy import hacks now 😐
(And again in this case they can use typing_extensions.Sentinel)
yeah backports help a lot with this
someone could publish a backports.sentinels or something else outside the backports namespace too
Unfortunately typing_extensions kind of falls into the heavy import category for the library I'd be using sentinels in.
We've never really spent any time trying to reduce the import time of typing_extensions in the same way as we have with the typing module. I'm sure there's some low-hanging fruit there if you fancy taking a look
To be fair, with this library I've been very careful about import time from the beginning. It's about a 2ms import on this (old) machine, while typing_extensions is closer to 30ms.
it depends completely what software you're running
I tend to think of it somewhat relatively?
if it's a long running server then import time is almost always irrelevant. If it's a command line utility that should run pretty quickly then long imports can become unacceptable
Yeah, this library is kind of dataclasses but everything is lazy (and now also potentially pre-cached) because I wanted to use it for quick command-line stuff
i admit, I haven't personally seen dataclasses become an issue, though I know people have talked about this before
python is just kind of slow in general so I'm mostly using it for things where my expectations are low, unless almost all the heavy lifting is in C
Dataclass construction is kinda slow and up until the new beta it also imported a bunch of other slow modules.
Again, relatively speaking
Like, if you're doing import numpy then dataclasses is relatively small
I do personally think the dataclass situation is a little bonkers in some sense. Almost every class I write is a dataclass, so that's an awful lot of codegen for very basic functionality
then that's probably why dataclasses has never bugged me 😛
it's not just import dataclasses itself being slow, but also every individual dataclass is slow
because executing the @dataclass decorator does a bunch of expensive work
Yeah, although until we improved the import time of dataclasses itself it was somewhat overshadowed?
interesting my intuition would have actually been what jelle said
i.e. I thought the actual codegen would be the expensive part
it scales with the number of dataclasses after all
I don't recall the numbers but I think it used to import inspect which is quite expensive? And enums are not great either
Unfortunate, I ❤️ enums too
I'm actually surprised how many python devs I've talked to who would rather use Literal type annotations over an enum
enum has a few more features than necessary
I love enums too, but the amount of work the EnumType metaclass does every time you subclass Enum is a little scary
that's probably true, but being able to iterate is pretty convenient
Yes inspect was the most expensive part, it also meant that you couldn't remove most of the other imports
Well you could, but then they'd still be imported by inspect
Mostly though I just like that enum lets you create a real type with defined alternatives
Literal feels very ad hoc, and you have things like different type checkers handling things differently
rust enums are really nice; i’ve honestly never used a Python enum
they're not really similar, naming aside
Rust enums can be used as "enums" but it's like two features rolled into one
Python enums are more like C/C++/Java etc enums
Yeah
Rust enums are sum types, it's just that sum types are a super set of C style enums
It does scale with the number of dataclasses and depending on their methods, but I think it's probably around 20 dataclasses before you catch up with the import time? Unless they're frozen. These are just guesses based on other ancient timings though I've not tested this recently.
(Well, the old import time)
oh, but 20 is peanuts (right?)
If Literal had a more ergonomic ability to iterate over its members and maybe support checks like a_str in Literal[...] (with type checker support), I think it would mostly replace features used in enum.Enum?
I was imagining like a decent size codebase, you could easily have hundreds of dataclasses
hundreds of different dataclasses 😰
it's a lot of if's. but also like... if you're coming from a statically typed language, I think Literal is pretty fundamentally icky because it makes no sense to talk about statically checking values unless you have rules for what it means for a value to be known statically
and python doesn't
from typing import Any, Literal
def foo() -> Literal["hello"]:
x = "hello"
return x
Maybe there's an option but this still doesn't type check on mypy 2.0 by default
Oh yeah, type checkers often lose the literalness of a value. Here's pyright: ```py
from typing import Literal, reveal_type
type Color = Literal["r", "g", "b"]
class Foo:
def init(self, arg: Color) -> None:
self._a = arg
reveal_type(self._a) # Literal['r', 'g', 'b']
def foo(self) -> None:
reveal_type(self._a) # str???
yeah. but like, you cannot really blame type checkers because none of this is even vaguely spelled out anywhere canonically, and it's non trivial
like, look at C++ constexpr rules, or Rust const rules - it's complicated. That's what we're talking about.
I accept the practical utility of Literal for typing existing code but I personally don't think it makes sense for new code in like 95% of cases.
For me it's very similar to typed dict vs dataclass in that sense.
Yes, you cannot just infer the type of every string literal as Literal. Otherwise e.g. it would infer py fruits = ["apple", "banana"] as list[Literal["apple", "banana"]] which is not very useful
yeah, since list is not covariant
it just becomes a mess
enums are totally unambiguous and at the call site it's also clear that you're passing one of several alternatives rather than a magic string
I think the main advantage literals have is concision. In some languages, you can write something like .RED instead of some_module.SomethingColorChannel.RED, which is of course impossible in Python
but I do agree that the inference rules make Literal janky to use sometimes
Well, yes, I was exaggerating a bit. (some codebases have a code style where you can only import modules and not individual items)
that's a pretty awful style for a typed codebase regardless tbh
https://google.github.io/styleguide/pyguide.html#22-imports
Use import statements for packages and modules only, not for individual types, classes, or functions.
Exemptions from this rule: <...>
typing module
collections.abc module
typing_extensions module
Redirects from the six.moves module.
but yeah, I mean the issues with enums to me - import time (almost always a non-issue), a little verbosity
still pale compared to the readability benefits, plus not ever getting caught in some kind of weird type checker case, type checkers disagreeing with each other, etc
I think that was a reasonable style before static typing in python
it's just now... def foo(x: some_module.FirstType, y: other_module.SecondType, z: longer_module_name.ThirdType):
google's python style guide obviously long predates type hints though and it's enormous so I can see why for them it makes sense to just continue doing the same thing
I'd definitely want to do as shortname at least
(Not helped by many of my own libraries being namespaced first)
I think kotlin was smart to disallow importing the "module", fwiw. ends all the discussions, code is more concise, and it's trivial for the editor to tell you where something is from
every language that allows both will have to have a style guide that will be endlessly argued about 😛
import ducktools.classbuilder.prefab
@ducktools.classbuilder.prefab.prefab
class Example:
a: list[str] = ducktools.classbuilder.prefab.attribute(default_factory=list)
Yeah not great
decorators is another place where I really dislike having the module name
I admit this is totally irrational
There's a base class version, which is probably actually worse
Especially if you start adding things like kw_only and frozen
Lazy generation is pretty nice for frozen as hopefully nothing actually triggers the __delattr__ or __setattr__ of a frozen dataclass
Did lazy imports not help the enums module at all?
Most of the import time of the enums module is the enums module, the only things it imports are sys, builtins and types
for me imports have never really been an issue in general so I can't comment. I was just mentioning it because some other folks had expressed it
Anyone think match-case will ever be expanded upon?
Been 5 years and nothing. Ive really wanted something more concise than below for checking if anything in a sequence is a specific type.
import numpy as np
def check(t):
match t:
case (a, b, c) if any(isinstance(x, np.ndarray) for x in (a, b, c)):
print("Contains a numpy array")
case _:
print("No numpy arrays")
There haven't been a lot of proposals. Maybe there's room for expansion, but "is a 3-sequence containing at least one member of a specific type" doesn't seem like a common need
the only expansion I wish for is the ability to refer to constants without requiring attribute access
Theres not much you can do with a sequence other than trying to match some fixed amount of items on either end.
It's really just asking for a way to match if there's at least 1 item in a sequence is a specific type or all the items in a sequence are a specific type without having to rely on a guard.
Some sort of more advanced predicates.
import numpy as np
match value:
case [*items] if any(isinstance(x, np.ndarray) for x in items):
print("Contains at least one ndarray")
case _:
print("No ndarray")
An example like this would be useful for json parsing, say a schema declared you'd receive an array type and there would be at least 1 item in the array of a specific type.
{
"type": "array",
"items": {
"anyOf": [
{ "type": "number" },
{ "type": "string" }
]
},
"contains": {
"type": "string"
},
"minContains": 1,
"maxContains": 1
}
The way id look for that item right now would be like
next(x for x in arr if isinstance(x, str))
A match-case that searched the sequence and allowed binding that a expected type to a name would be useful. Which is really how I'd want to use it. The numpy example was just first thing that came to mind.
Side note:
For that numpy match case example
Something I just realized, doing a sequence check like above doesn't match a string but will match any other kind of sequence
a random thought - in free threaded python, you can easily just use asyncio for CPU parallelism, can you not? Especially if you just raise the number of threads in the default thread pool executor.
You can currently "bridge" between asyncio and cpu parallelism by using run_in_executor and a process pool, it's just more clumsy
with free thread python you can use asyncio.to_thread, which makes it way, way more elegant
I've been dealing with some code that originally used process pool executors, and then also thread pool executors... and now there's asyncio in the mix too. And it's just a mess. there's a "--parallel" option that simply doesn't work because you can't naively mix asyncio and thread pools.
Would be very nice to just be able to use asyncio as a singular abstraction that handles it all
not quite sure if I follow your full idea, I don’t have much practical experience with asyncio
import asyncio
import time
def work():
print("start work")
time.sleep(10)
print("end work")
async def par():
await asyncio.gather(*[asyncio.to_thread(work) for _ in range(5)])
if __name__ == "__main__":
asyncio.run(par())
with free threaded python you can just write code like this
and we get parallelism with really minimal syntax and without having to explicitly deal with a process pool or what not
maybe we just need cancellation and timeouts for threads
with GIL python you'd have to write this
import asyncio
import time
from concurrent.futures import ProcessPoolExecutor
def work():
print("start work")
time.sleep(10)
print("end work")
async def par():
loop = asyncio.get_running_loop()
with ProcessPoolExecutor(10) as e:
await asyncio.gather(*[loop.run_in_executor(e, work) for _ in range(5)])
if __name__ == "__main__":
asyncio.run(par())
it's just significantly more awkward as you can't use the default/global asyncio executor (since it uses threads)
so you have to pass around this separate process pool for the CPU work
yeah, I think this is an underappreciated bonus of free-threaded Python
similarly I’ve found that thread pools are a lot more ergonomic practically for real-world stuff than process pools
non-trivial real-world stuff often runs into arcane gotchas around pickleability
Yeah. Or just the fact that you can't pickle a lambda. Performance issues of needing a large amount of read only data in each process. Etc. Certainly a lot of issues. But even compared to thread pools this is quite nice, if you end up using asyncio elsewhere in the program
Random question - is there any particular reason that the asyncio.subprocess stuff is like... almost the same as subprocess, but with various weird annoying differences?
Mostly, a lot of convenience API has been removed - e.g. capture=True, text=True was very convenient
also, rather than shell=True/False there's two separate functions. Maybe this is because it affects the type of the command arguments I guess? But feels a bit random
One of the things I really liked is when subprocess.run came out, the API and convenience functions were good enough that I basically stopped having my own wrappers around subprocess functions
feels like now I'm headed back to that
Good questions
I doubt they just wanted it to be different from subprocess but yeah
yeah, I think maybe asyncio predates subprocess.run, so that could be part of it
I don't nothing about programming. Can anyone suggest a good YouTube playlist or books to learn about programme fundamentals. I meant to learn A,B,C s... Where should I start.......
!learn
Here are the top free resources we recommend for people who are new to programming:
- Automate the Boring Stuff — an online book (also available to purchase as a physical book)
- Harvard’s CS50P course — video lectures (slides and notes provided) with exercises
- Python Programming MOOC 2026 course — text-based lessons with exercises
- Corey Schafer's YouTube playlist
For a full, curated list of educational resources we recommend, please see our resources page!
(also, this is the wrong channel; check out #python-discussion )
Good afternoon guys, tomorrow is my PCEP test Where can i find practice questions and leaked exams questions?
You may have misread PEP as PCEP
!clban 648479497775218698 scam/malware/piracy
:incoming_envelope: :ok_hand: applied ban to @hoary token permanently.
hi
Hi, everyone
hi. the general channel is #python-discussion. You can help by hanging around and joining in conversations.
Okay. I have already complected Pyhon projects. Okay?
Okay
Good job
thank you.
So import statements inside a try/except block are eager even under -Xlazy_imports=all but imports inside those modules are lazy again so if the import error that is being guarded against is actually from a submodule then the import is successful when it would have failed normally.
Ran into this trying the mode with pip so it's not entirely hypothetical
Well I had to build Python without some optional dependencies but I guess this is a bug?
$ PYTHON_LAZY_IMPORTS=normal ./python -c "import shutil; print(shutil._BZ2_SUPPORTED)"
False
$ PYTHON_LAZY_IMPORTS=all ./python -c "import shutil; print(shutil._BZ2_SUPPORTED)"
True
Technically that one could be fixed by trying _bz2 instead of bz2. I think that's the only one in shutil affected by this as the others use the internal module at top level or have a * import 🤔 .
Not sure if there are other cases like this elsewhere in the stdlib though. That one came to mind as I'd seen those try/except checks recently.
that's nasty, please open an issue
Yeah I'm in the middle of doing so
keep them coming 🙂
I'm looking back at something which bothered me when I first opened the functools.cached_method PR. (Thanks to everyone who has helped me get it this far, btw!)
I see a number of things in functools set __class_getitem__ = classmethod(GenericAlias). Dates back to this commit. I don't quite understand what that does, since I've never been 100% clear on what GenericAlias is/does. Is this something I need to add to cached_method?
It would mean that functools.cached_property[int] == GenericAlias(functools.cached_property, (int,))? Is that what we want?
Oh, I see now -- asking made me test more stuff -- that this doesn't include lru_cache or cache, since those (like cached_method) are functions. So I guess this is fine? It seems slightly inconsistent to me, but I don't quite grasp what the purpose is of it being possible to write functools.cached_property[int].
it’s for static typing, see PEP 585
I guess there's the question of what it means for cached_property though? You can't do property[int]
To the above regarding GenericAlias, I feel like I don't "get it" when I see it outside of the context of builtins, e.g., list[str]. Tracking this through BPO, it seems that functools.cached_property was generic in typeshed, so we made it generic in the stdlib... Maybe it's just a sort of accident of history?
you can see how the generic parameter is used in typeshed: https://github.com/python/typeshed/blob/df452876bbcabefe36ada5f956a06beb859d778d/stdlib/functools.pyi#L248
I think it's there so that when the type checker sees the decorator applied to a function of type (...) -> T, it knows that cached_property will make a descriptor that resolves to T
stdlib/functools.pyi line 248
class cached_property(Generic[_T_co]):```
I don't see much of a use case for explicitly writing cached_property[T] but I guess it could make sense if you work with cached_property objects directly
I was actually thinking of opening an issue on CPython about documenting better why we make certain things generic. All the docstrings for C-implemented __class_getitem__ method are just "See PEP 585" and that doesn't tell you much. We should list what the expected type parameters are and what they mean.
i would forbid PEPs as explanations. We should write real explanations, and link to PEPs only for people interested in the historical process.
I'm going through these, and finding many things that are generic in typeshed but not in cpython... that subscriptable functions PEP is looking more appealing by the minute.
I am taking a look at the python lexer and for some reason :
a = 10 #asdasdsa
the newline token has the start at the start of the comment;
[NEWLINE](7 - 17)(start = 0x60eaa7f1b1f7, end = 0x60eaa7f1d1f0): #asdasdsa
I don't think the subscriptable functions PEP is relevant here — cached_property is a class, not an instance of types.FunctionType
Oh, I was thinking of the other stuff. functools.partial (which is a function) and functools.chain (which is a class but is documented as a function with a classmethod on it 😵💫 )
functools.partial is a class too, I think? And itertools.chain might be documented as a function, but it's still not an instance of types.FunctionType at runtime, and the subscriptable functions PEP is only really relevant to things that are literally instances of types.FunctionType
You're right about partial -- I just checked. I think there are some mixed up cases though.
https://github.com/python/cpython/issues/108761 and https://github.com/python/cpython/issues/112896 for some related discussion
Feature or enhancement Right now it is impossible to subscribe map: » ./python.exe Python 3.13.0a0 (heads/main-dirty:79823c103b6, Aug 31 2023, 15:46:08) [Clang 14.0.3 (clang-1403.0.22.14.1)] on dar...
Thanks for the refs! I was going through things today (doing the docs update discussed above), and saw that enumerate implements class getitem. map and filter feel a bit different.
for those that were involved with PEP 585: why did we add a new dunder instead of just implementing __getitem__ on type?
not all types need to be subscriptable
though then again class getitem doesn't check argument counts either
I wasn't involved in the discussion
do we implement it on any non-C types? I was thinking we could have used a type flag
Yes, it's implemented on quite a few stdlib pure-Python classes
In typeshed we can pretend that these classes inherit from typing.Generic, but we don't want the whole stdlib having a dependency on the typing module at runtime
It would create a horrible mess of import cycles
My way into this as a topic was seeing classes which have __class_getitem__ = classmethod(GenericAlias) -- you can grep for that to find many of the cases
And it would also make runtime startup slower for projects that are uninterested in typing, which is undesirable
inb4

So how about that walrus?
In Java, can't you already do assignment within if statements and such just using the regular = operator?
well, this is new.
I didn't really get why it had to be a separate thing, but I like it otherwise.
4th message in new python language channel: java
Do you mean if (int I =0; ...)?
I don't know, I only use Java when my professors don't give me a choice.
but I thought I saw something along those lines. Though I don't think there's ever a semicolon in if conditions.
A choice was made to introduce := instead of expand the legal cases for =
It might be that the latter would cause ambiguities that haven't occurred to me.
I think it would've been a lot less controversial if they hadn't used the colon.
but the thing @true ridge just linked raises a good point
not entirely convinced it was worth the trade-off, though.
I don't know if you folks run into it, but seldomly I write = instead of == which would make the expressions always True (depending on the assigned value)
it is nice to have a different operator for this job, it makes the purpose a bit more explicit
yeah, and that case would be a bit insideous.
I never fully understood the conflict behind it though, surely if people disliked it they could have just not used it (though I'm sure this was a point raised many times), I personally quite like the := operator (though wish flake8 and co would support it)
ah it might be, it just wasn't when I tried to add it to @fallen slate
I know I tried it on the stats PR so that was like April 12th
who is flake8?
a linter
a very nice one
yep, the maintainer just released it
oh snap
anyway sure, := doesn't bother most of us here that much but it fragmented the community at the time and I think it has hurt adoption quite a bit.
the = did the same thing until 3.8 so I think changing that instead of including the new walrus could cause some confusion and potentially make a lot of resources outdated
it would still be backwards compatible, it would just fail to give an exception if you confused = for == in a comparison.
possibly introducing a silent and deadly problem
how do i do like
str = so mething
first_part = #everything before " "
and also
everything after " "
There are examples of changing a statement to expression, like yield. But because of its limited usage and purpose of it, it didn't hurt anybody.
@fair lynx if you claim a help channel and ping me, I'll answer that.
For assignments, it would definietly hurt some people and alter behaviors / create bugs that might be hard to spot.
okki
@fair lynx not sure what you're asking but this is not a help channel.
sorry ;-;
it is a common mistake by beginners that could go unnoticed until too late or much frustration, = is fundamental to the language and while it would be backwards compatible it's still a somewhat major change
and there are design decisions to differentiate them like invalid syntax at the top level
@dawn hill You lost your mind long ago.
It's python discussion for actual python discussion
am good for my question i found arcticles
Wasn't python-discussion for actual python discussion before #internals-and-peps ?
Yes but that didn’t happen
Fair enough
yes but everyone used it like it was #python-discussion
so now they can use that instead.
ohh so its .split
Fair enough
we want this channel to be a more intermediate to expert level discussion channel for conversations about the language itself. so this is a pilot test to see if this will help
Speaking of which
I'm still interested to know how feasible it would be to have optional compile-time type checking
in the language itself?
My friend who hates Python was complaining that it takes him a long time to debug type errors.
Yes
It's probably plenty feasible but they'll never do it.
For example, imagine if python -T my_file.py caused that to happen
the type system is intentionally left open ended and flexible because it's more pythonic.
but there are some pretty mature third party solutions for this now
mypy is excellent
Doesn't mypy turn running your code into a two-step process though?
checking it with mypy, and then running it?
no
mypy will only check when you want, possibly somewhere in your development workflow or CI. And when you deploy your code, the type annotations will have no meaning at all
or the mypy itself
Your editor likely supports it in some way
I get errors as I type (or save?). No need to run it manually
My friend who hates Python doesn't accept IDE-dependent solutions. Not that his objection to how Python is designed necessarily important, since it doesn't look like he's seeking out a career where he'd ever use it.
yeah I've met lots of people just like your friend
not sure there's any convincing them. a type error ruined their entire life one time and now they're jaded and broken
lol
:/ I've never had that issue. It's just nice to avoid as many bugs as possible
I've only ever worked on one big project, and I haven't looked at it much since covid started.
Prevention is the best approach, IMO
but I think keeping the actual type checking in third party mostly is a strength of the Python language.
it's just more flexible.
but I didn't repeatedly have type issues.
I agree with @fossil pumice; annotations aren't only for type hints, they are for storing arbitrary data inside of both runtime and compile time
so ecosystem is able to create many different tools to process code integrity with them
the true purpose of annotations is creating magical classes with metaclasses using __annotations__
i created a class that binds functions to properties through annotations:
class Relay(Dispatcher, default=0):
width: observer1
height: (observer1, observer2) = 10
Anyone knows how could i melt or self destruct a file after executing?
not very inclined to tell you how
yep, doesn't sound like a question for this channel or this server
Melt or self destruct? There are two totally separate methods
@deft pagoda how does that work? I've been trying to figure it out and I can't tell
Self delete from computer?
there's a lot of machinery in the Dispatcher class
@karmic agate we're not going to help with that here.
Why not?
5. Do not provide or request help on projects that may break laws, breach terms of services, be considered malicious/inappropriate or be for graded coursework/exams.
this is just the meta for it:
class DispatcherMeta(type):
def __prepare__(*args, **kwargs):
return DummyDefaultDict()
def __new__(meta, name, bases, methods, **kwargs):
methods = dict(methods)
module = modules[methods['__module__']]
default = kwargs.get('default')
for name, attr in tuple(methods.items()):
if isinstance(attr, Dummy):
if hasattr(module, name):
del methods[name]
else:
methods[name] = Property(default)
for name, funcs in methods.get('__annotations__', {}).items():
methods['__annotations__'][name] = tuple(getattr(module, item.name) for item in always_iterable(funcs))
return super().__new__(meta, name, bases, methods, **kwargs)
but it was mostly an academic exercise
Im not into anything malicous tf
@karmic agate
- this is the wrong channel, no more discussion here
- even if you use it with no malicious intent, someone else will, we are not risking it.
Bs
You can see from the description of this channel that it isn't for help.
Yeye bye
so im kinda a beginner in python, I'm coding a pong game and I can't fugure out what my mistake is. Prolly some stupid small mistake but can sum1 skim thru my code and tell me if they can catch what I did wrong?
Hey @unkempt rock!
It looks like you tried to attach file type(s) that we do not allow (). We currently allow the following file types: .3gp, .3g2, .avi, .bmp, .gif, .h264, .jpg, .jpeg, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .png, .tiff, .wmv, .svg, .psd, .ai, .aep, .xcf, .mp3, .wav, .ogg.
Feel free to ask in #community-meta if you think this is a mistake.
@unkempt rock use a help channel.
This channel name might need to change lol
which one
hm.
then we'll just talk about sanscrit, and what not. 😉
python-channel-but-not-a-python-help-channel
Beautiful, ELA has it
A bit long
(not help) python-language
so im kinda a beginner in python, I'm coding a pong game and I can't fugure out what my mistake is. Prolly some stupid small mistake but can sum1 skim thru my code and tell me if they can catch what I did wrong?
bruh
lmao
hahaha
Enough
@unkempt rock please, please use a help channel.
@unkempt rock Use a help channel starting with ✅ emoji. If you don't know how, see #❓|how-to-get-help
honestly language is concise
we don't need to specify that it's python because we are literally in a python discord
language is okay. it's not very precise.
language-(not-java)
I don't hate it but I don't love it.
that's like having a folder called "School" and then a subfolder called "Algebra in School"
you don't need the "in School" part
I love naming my variables!
python-channel-but-not-a-python-help-channel
Imo ELA nailed it
-lang is also considered mostly used for programming language stuff
rust-lang, etc.
But it might have the same problem
I love packages that needlessly include "python" in the name, good to see a discord channel doing the same lol
speechless
the pypackage is also funny
@misty mulch yeah we should've just called this server Discord
pydantic is my favorite
:o
I like F1re's idea
I guess we can't do reactions here?
I actually kinda like language.py
of course dots aren't legal for channel names
so it would be like language-py instead
This more belongs in #community-meta but the ✅ isn't a very good emoji for "avaliable"
language-dot-py
which is less nice
you could use some unicode right?
Do it like how Wikipedia names the article for C# "C sharp"
and then the top of the article says that the real name of the article is "C#"
you could use some unicode right?
@north root
it's possible. not aware of a working dot Unicode for discord channel names
but maybe.
Okay, I think if we keep python-language we also need to create a channel for python-snake
It's only fair
we also need a monty-python channel too

flying-circus
and a python-logo
(that's what offtopic-0 would be)
I think I will allow this blatant offtopicery since it's a meta conversation about this channel.
and a python-colorscheme
haha
but please don't use this channel for this later on.
monty-python is redundant, just a monty channel is needed
lmao just #monty
I feel like language is the best choice
@fossil pumice
Since we can't do language.py
use this dot
lol
U+2024 ․
ahh lossberg found it first
it has weird name ONE DOT LEADER
Let's commit to the langauge misspelling, I like it
I really don't think using a . makes sense
it's inconsistent with the rest of the channel names
I root for py-language
I personally don't mind the inconsistency but that's just me
I like it too. in fact, I'd be open to changing #discord-bots to use the dot, too.
@worldly venture thoughts on dotting channels and language.py for this channel?
Woot Woot my message is pinned 😂
ooh that's nice
discord.py would make lot of sense. Also esoteric.py heh
https://paste.fuelrats.com/ibihexateq.txt for some channel chars
I feel bad for the guy who decides to make a bot that has any interaction with these channels
nice
You'd probably use the name of the channel and fetch the ID with the name, rather than hardcoding the ID tho
Also it was just a joke
@worldly venture what about discord.py
Oh damn, so name change?
discord.py makes sense, language.py doesn't because the .py doesn't hold much significance besides "it's python"
like.. at all?
They'd work with autocomplete, wouldn't they?
it'll autocomplete wouldn't it?
if you autocomplete they will yeah
that's probably okay.
I do see @unkempt rock's point as well
Who don't use autocomolete tho for channela
me
Wait what channel is being changed?
i usually just do <# and then type the channel ID from memory
Can I just 🤦🏻♂️ 😂
lol
yeah I mean discord.py i'm 100% with, language.py I'm okay with but don't really have an opinion
Idk at who tho full typing name or channel id lol
Isn’t discord.py a library?
I think language.py is weird enough to maybe keep general questions out of it. I don't like just language
Also Isn’t there already a channel in this server named “discord-py”
what about #cpython
yeah, that is what we are renaming
I wonder if that would work
oh? I thought python-language included other compiles
Ohh, right
So in future would this be a good place to discuss smth like how useful are type annotations and why people use or don't use Them
fiine, I guess you're right.
I held off on saying #cpython because I thought it also included other implementations
it'd be fine to discuss other pythons here
kinda like that, yes.
I read, that's what prompted me to ask
what are benefits of using programs? they are just browsers in a box... like discord
I don't think #python-meta quite works.
because otherwise python-language is misleading
I dont think anything that starts with python- would solve the problem
exactly
python-meta is like meta, but for python not the server
that was the original name
language.py would be a pretty cool name
I know
Rename this channel circulardebateoversemantics since that reflects its content
it people see the word discussion and think general chat
^ I did
@misty mulch thanks for that valuable contribution
oops that should be in general*
honestly, I don't know why we give the off topic channels numbers if the phrase after it is unique
but why is that needed
so two days from now i can find the discussion i was having in an ot
Its much easier to link to a channel
I see
Especially if you discus while name is changing and what to refer to the Chanel
I don't want to have to type #cheesey-toes or whatever to link to it. #ot{number}+tab is much nicer
yeah, that makes sense
!otn a cheesy-toes
:ok_hand: Added cheesy-toes to the names list.
hahaha
Petition to delete all keywords
And let user select which set of keywords they want as pre defined

Also force var def to specify type
hahah that would get rejected so fast
We could infiltrate the steering council
with our little Discord cabal
I forked cpython a while ago to make my dynamicdict
though that got a hard no from the one core dev who responded.
>>> my_dyd = dynamicdict(str.upper)
>>> my_dyd['hello'] += ' world'
'HELLO world'
The missing key gets passed to the default factory.
defaultdict does not support that behavior.
This example is useless, of course.
I created it because I wanted it for something I was working on
I've been meaning to submit it to the pypi
it's here: https://github.com/swfarnsworth/dynamicdict
performance idk?
I mostly wanted to see if I could do it.
But I do legitimately think it's worth while.
yep
I'm not sure why that's not the default implementation of defaultdict, because you could do all the same things if it were
defaultdict(lambda x: [])
now you have defaultdict(list)
less elegant though for those cases, for sure.
if defaultdict tried to pass the key to the default factory, but the default factory didn't have any parameters, you'd get an error.
so if defaultdict supported key-based generation of missing values, the default factory functions would all need to accept one argument, and ignore it if need be.
yes
I wanted it to be a separate class
but no one liked it
😢
This can't exist in Java
because it's illegal to have an operation in Java that could be done in Python in one line
unless it takes at least three lines in Java.
I'm just making fun of how verbose Java is.
It just seems uncharacteristic of Java to me to abstract away as much work as dynamicdict or even defaultdict do.
but I could be way off
This is pretty neat
i've created some defaultdicts lately that only add some missing keys and not others
for metaclasses
that would be a neat keyword arg
that is, extend the functionality of defaultdict to support this behavior with a keyword arg?
hmm
another lambda probably
in what case did you use this?
ignore: lambda key: key.startswith('__')
for __prepare__ method of metaclass
consider this simple case:
from itertools import count
class IncrDict(dict):
def __init__(self, start=0, step=1):
self.counter = count(start, step)
def __missing__(self, key):
if key.startswith('__'):
raise KeyError(key)
self[key] = next(self.counter)
return self[key]
class EnumMetaclass(type):
def __prepare__(*args, **kwargs):
start = kwargs.get('start', 0)
step = kwargs.get('step', 1)
return IncrDict(start, step)
class Enum(metaclass=EnumMetaclass):
def __init_subclass__(cls, **kwargs):
"""Pull kwargs from class def"""
class Fruit(Enum, start=10, step=15):
APPLE
BANANA
print(Fruit.APPLE, Fruit.BANANA)
10 25
it has enums, but this enum is cooler
I'm sure it is 
also, today is the first time I've seen keyword arguments in class declarations
i've been doing a lot of metaclass stuff recently for my own amusement
Oh that's actually cool, I didn't know you could do that :o
I guess this is calling __init_sublcass__ of each class in the new class's MRO?
you can pick up the kwargs in __init_subclass__ or you can grab them in __new__ of the metaclass if you define it there
speaking of which
yeah, __init_subclass__ gets called before any of the subclasses body
__new__ is a class method that actually does the instantiation, right?
so you can do some major surgery there
if you override __new__ in a subclass, how do you ensure that the instantiation still happens?
yeah __new__ will return the instance
__new__ of object creates the instance
so you have to access that through super(), or call object.__new__()?
you can use super
but if you do that
do you have to do
def __new__(cls):
new_obj = super().__new__()
new_obj.__class__ = cls
return super().__new__(meta, name, bases, methods, **kwargs)
😮
isn't that just for type salt?
that's for metas
hmm
i've been experimenting with automatically binding properties in class defs through metas
In [30]: from dispatcher import Dispatcher
...:
...: def observer1(instance, name, old, new):
...: print(f'{name} from {instance} changed from {old} to {new}')
...:
...: class Relay(Dispatcher, default=0):
...: width: observer1
...:
...: relay = Relay()
In [31]: relay.width
Out[31]: 0
In [32]: relay.width = 10
width from width(<width=10, [observer1]>) changed from 0 to 10
there's a lot of machinery in Dispatcher
the repr is bugging me though
i can't figure out what i did for this to happen:
In [60]: Relay.__name__
Out[60]: 'height'
oh, i found it
i shadowed the name variable in __new__
I had a question, I added mingw 64 bit as my compiler but how do I make a path to it to visual studios
that's not related to python, so try one of the off-topic channels
@north root https://gist.github.com/salt-die/1adebb3639ded8e1215b2fa2584d0583 here, there's a small demo file at the bottom
yeah, it's a pretty deep dive
can somebody explain the benefits of using lambda?
I keep seeing it in a lot of code practice, and I don't get it.
It's good when you need a small function in one location
Something that wouldn't be worth creating a new regular function for
That's fair.
useful for the key kwarg in sorted/min/max
from dataclasses import dataclass
@dataclass
class Student:
name: str
grade: float
students = [...] # list of Student objects
# Get student with highest score
best_student = max(students, key=lambda s: s.grade)
print(best_student)
@noble mesa
you can make dataclasses comparable so you don't have to provide a lambda function
but
then it wouldn't illustrate how lambdas work
and I'd have to come up with a new example
ahhh
also you might want to alphabetize your students or something
and then you'd have sorted(students, key=lambda s: s.name)
from dataclasses import dataclass, field
@dataclass(order=True)
class Student:
name: str = field(compare=False)
grade: float
My example is ruined 😦
hahahaha
@boreal umbra I can ruin that even more: use operator.attrgetter instead of a lambda
!e
from operator import attrgetter
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def __repr__(self):
return f"Person(first_name={self.first_name!r}, last_name={self.last_name!r})"
people = [Person("John", "Wick"), Person("Guido", "Rossum, van"), Person("Lemon", "Beardfist"), Person("Joseph", "Posh"), Person("Charlie", "Wick")]
print(sorted(people, key=attrgetter("last_name", "first_name")))
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
[Person(first_name='Lemon', last_name='Beardfist'), Person(first_name='Joseph', last_name='Posh'), Person(first_name='Guido', last_name='Rossum, van'), Person(first_name='Charlie', last_name='Wick'), Person(first_name='John', last_name='Wick')]
Is this channel a non-weird version of #esoteric-python?
from dataclasses import dataclass, field
@dataclass(order=True)
class Person:
first_name: str = field(compare=False)
last_name: str = field(compare=False)
last_first: str = field(init=False, repr=False)
def __post_init__(self):
self.last_first = self.last_name, self.first_name
@undone hare that's basically the idea, yes.
there's probably some nicer way to switch the order
@deft pagoda Sure, that's if you always know which attributes you're going to compare, and want to preprocess it
If you want to combine attributes of existing objects in a comparison or other thing, that's where operator.attrgetter comes in
Or things like itemgetter
also why does the discord syntax highlighter break when a ( directly follows a function
print (
print(
It does not break, it just supports "print as a statement" from Python 2
i thought it was highlighting builtins
No, just things like statements and operators
If you add a ( after return it doesn't change color, as there's no return-function.
It's a special change for print, I think, to make "print-as-function" look like other function calls
well, i'm voting for function highlighting at the next discord syntax meeting
Maybe one day multi-line decorators will not look weird
Oh well, I'd prefer to have a mobile highlighting than anything else
I think the syntax highlighter for python should split into py/python/py3 and py2
instead of trying to do both
I do see Python 2 being mentioned less and less. It's not gone away, there are people who still need to maintain legacy systems, but I hardly see anyone singing the tune of "I'm never never never going to use Python 3; it will destroy the language!". Probably becuase it's pretty evident that it's not the case.
Most of the mentions I see are either from people using outdated (and free) resources and/or universities/educational institutes that got outdated in their teaching materials
hmm ive seen a few people say that python 2.7 is the best
those people were wrong.
It was quite a common sentiment a few years ago
When people were still resisting change
I'm not talking about the people who's job suddenly got more difficult by having to migrate, I think most yellers were not in such a position
having worked professionally in a py27 codebase, I have no idea why people say that other than because they don't want to migrate
And then there were books like Python, the Hard Way that gave people a bias just because the author was, well, I don't know, antagonistic to change? stuck?
A lot of programming languages evolve over time. If you refuse to accept that, your knowledge is going to get outdated
i missed the transition
A yeah and a half ago when I wrote my first line of python I was reading some article on should I learn py2 or 3. And it made case for py2. Luckily for me I only wrote one small program in py2 and abandoned it for another 4-5 months. And after I got some cheap Udemy course teaching 3
And now I am annoyed that In production my company has 3.5 and I can not use fstring
Python, the Hard Way was one of the books I picked up when I tried Python again after a few years
It was very biased towards Python 2, so I started with that
I regret that decision
There was a bit of a jump pre-3.5 to post-3.5 for asynchronous programming
3.5 introduced the async def and await syntax that replaced the older decorator-based coroutines
I've not had much issues with migrating code after 3.5
In most cases, py3.x code will run in py3.y if x < y.
Sometimes there are subtle differences that may surprise you
Such as that CancelledError is now derived from BaseException instead of Exception in 3.8
It's probably a change for the best, but it does mean except Exception won't catch CancelledError (which was the point)
There are probably other examples of such small changes that could lead to unexpected differences in behavior
Reading the changelog for each minor version would tell you that
It's unlikely to be introduced within a minor version
yes
what evn is __init__subclass
It's a very useful method for when you're doing metaprogramming. Whenever you create a subclass of a class implementing __init_subclass__, that method is run, just like __init__ is run when you create an object from a class.
A lot of the things that used to require meta classes can now be done with __init_subclass__
does it run both of them?
What do you mean?
__init_subclass__ runs when you define the subclass
Not when you instantiate an object of the subclass
It's one of those methods that helsp you avoid metacalsses
__set_name__ is another one
that's new to me, too
Say that you write a descriptor that needs to know the name of the attribute you're assigning it to
The usual way of solving that was by using a meta class
Now __set_name__ gets run when you assign a name to something
So, you get access to it within this dunder
!e
class Foo:
def __set_name__(self, owner, name):
print(f"I'm assigned to {owner!r} as attribute {name!r}")
class Bar:
attribute_name = Foo()
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
I'm assigned to <class '__main__.Bar'> as attribute 'attribute_name'
This is useful for instance when a descriptor wants to store the data in the instance's dict using the attribute name
i have a lengthy demonstration of both in a gist somewhere