#internals-and-peps
1 messages ยท Page 131 of 1
i forgot about that lmao
pretty much
unless i'm using some frickin' large hadron collider crap 1 microsec is good
1 microsecond per decorated function at import time, would need to be importing a lot of code to be sweating it
besides, partial has way more readability
yeah, and the triple definition is just really weird (i didn't even implement optional parameters yet, that would make it worse)
how would the implementation without partial even look without copying the function?
wdym by "copying the function"? it just redefines one each time ๐
triple def
update_wrapper is its own public function, you would need that under your def if you wanted to get rid of partial or similar functionality
if you really want it to be fast just paste the decorator code inline in every function, ez
oh yes, true
ah, so this is why functools opted for partial
you were right, @peak spoke, they need it to also be a standalone function (for decorator classes)
and readability is the cherry on top of the cake
thanks y'all for figuring this out with me!
Hi Guys
I want to do something like that
using django rest framwork
anyone can help me?
I tried this
that's perhaps a better question/problem for #web-development if it's a question in general or #python-discussion if your question is specific (ex. "what does this django function do?")
class ServiceImageSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ServiceImage
fields = ['photo']
class ServiceSerializer(serializers.ModelSerializer):
images = ServiceImageSerializer(many=True)
class Meta:
model = Service
fields = ('id', 'title', 'description', 'features', 'images')```
this is #internals-and-peps, we discuss python's advanced features, implementation details, use cases, and its future
Eating your own dog food or โdogfoodingโ is the practice of using one's own products or services. This can be a way for an organization to test its products in real-world usage using product management techniques. Hence dogfooding can act as quality control, and eventually a kind of testimonial advertising. Once in the market, dogfooding can dem...
๐คฃ lmao yeah, maybe also that
functools using functools :D
the following are all more or less equivalent:
- creating a closure that passes some arguments into another function (the "double-nested" decorator technique)
- creating a callable class
- partial function application
in fact i think partial is implemented using the 2nd one? but maybe in C and not in pure python
or maybe it's pure python which is why it has extra overhead
my guess is no, but is there anyway to start off with a TypedDict like this:
class ABC(TypedDict):
a: int
b: str
and then feed a set[Literal["a", "b"]] to then get another TypedDict permitting only the keys within that set?
my use case for this is SQL queries. I have a function that returns a TypedDict after executing a "select *". But this returns a lot of unnecessary data which I have profiled to be a performance problem, so I want to only grab the relevant columns. But I want to statically type this. So idea is that this method takes a set[Literal["the", "relevant", "keys"]] and returns a TypedDict only allowing those keys. There is another TypedDict that serves as the source of truth for every column's type (I automatically generate this from my SQL DDL), so I'd want to generate the query-specific TypedDict from that base TypedDict
we use pydantic, but for runtime parsing of values. when you say it sounds similar, do you think the above functionality would be present in the mypy plugin from them as well? if so, i'll check it out, since I'm trying to do this at type-hint time
i would consider dataclasses for creating typed data structures at runtime https://docs.python.org/3/library/dataclasses.html#dataclasses.make_dataclass
then you can have a helper to make the dataclass type from a set
curious if mypy can validate this..
this gets close (assuming mypy can validate it), only thing that could be better is not having to specify types again. So keeping a single source of truth for the types (a dataclass containing all the fields), and using that source of truth + key names to create the new dataclass instead of having to specify each type again in the tuples. But sadly that's not possible
looks like make_dataclass accepts annotations, which you can pull from the single source of truth
tbh i would probably make all the query types explicit TypedDict or what have you with some automated test to validate the fields and their annotations against the canonical master list
have a common base class then you can iterate over __subclasses__ for validation
this 100% satisfies mypy and you can probably do it with pydantic too
and you probably get better hints in your IDE etc. etc.
yup, best option would have been to autogenerate. but second best option is to duplicate types but then validate that they are in sync. Instead of iterating over __subclasses__, I'll just check that the type-hinted return type of each method is actually accurate at runtime during the integration tests when talking to the database
thanks a lot for the help
Not without AST manipulation. There is very limited facility for "computation on types" in Python
I think this is a great idea though
It's like the clojure spec "select" proposal
This is one of many reasons why I am starting to seriously look into Hy as a serious tool
Because you don't have to write type checker plug-ins and implement your own primitives, you just write macros that expand to annotations that already are supported
That said I really should learn how to write a mypy plugin
this: https://github.com/hylang/hy, right? I will check it out
I have a lot of ideas for things like this I am really just need to make a PoC
Yep
Beware it's changing a lot during the alpha
I wouldn't rely on it until 1.0 comes out stable
I also need to contribute some optimizations to the code generator, specifically removing dead code that gets generated in if/elif and function definitions
maybe one day typing itself will evolve to support the functionality, but I do like the direction it is going down so far. ParamSpec / Concatenate are already something I have a lot of uses for (mainly authentication decorators)
The one thing we don't yet have is the ability to operate on concrete types that have already been defined
ParamSpec works for parameterized/generic types
But there's no ability to "clone" the type of an existing binding
You just have to copy and paste it
I've previously proposed ParamSpecFrom and ProtocolFrom but I think those aren't general enough. I'll have to ponder it more before I make a serious proposal to typing-sig
The former would be extremely useful for subclassing, the latter for making protocols out of existing concrete types.
So in your case you should imo be able to do something like create a protocol from existing type, and then slice a subset of attributes off of it
No reason such a thing shouldn't work with typeddict
And if there isn't a known annotation for the thing, then it uses the same logic as for other untyped bindings
i.e. Any or object, depending on your mypy config
I don't think this is possible in traditional statically typed languages without dependent types, but I don't see a reason it shouldn't work
Maybe somebody with more formal CS/PL theory training can set me straight
erf, why is ```
randomPoint = random.randrange(newStartPoint, newEndPoint)
giving me a number outside the range ?
what are the actual values you are using, and the result?
newStartPoint: 56524
newStartPoint: 57944
randomPoint 109305
that is console log. This is within a program that has Py support. Davinci Resolve, thinking its that, cant get it to happen in py console
hmm, the label should say newEndPoint, but can we see the actual code also?
it also helps if you use a random.Random() instance with a fixed seed for generating random numbers. in general it helps make your results reproducible, which is good for testing and debugging
(it's mostly used by scientists for making sure their research is reproducible, but it has benefits for other users)
ahh endpoint seems to be off
some reason ia ssumed the second newstartpoint was my endpoint just using the wrong label
>>> a = [0, 1, 2, 3]
>>> *a[1], b = a
>>> a
[0, [0, 1, 2], 2, 3]
>>> b
3
>>> *a[1:3], b = a
>>> a
[0, 0, [0, 1, 2], 2, 3]
>>> b
3
```lol, python's `*` syntax on assignments work on subscriptions, slicings, attribute references, and nothing... literally:```py
>>> *[], [] = [[]]
>>>
There's the checkmark at the top. This isn't really on-topic for this channel, though.
lol..
>>> *[]
File "<stdin>", line 1
SyntaxError: can't use starred expression here
>>> *[], []
([],)
!e *[], [] = [[]]
@naive saddle :warning: Your eval job has completed with return code 0.
[No output]
class SyntaxError(Exception):
"""Base class for exceptions raised by the parser."""
def __init__(self, msg, lineno=0, offset=0, text=None, filename=None,
lastlineno=0):
self.msg = msg
self.lineno = lineno
# NB: offset is a 1-based index!
self.offset = offset
self.text = text
self.filename = filename
self.lastlineno = lastlineno
def find_sourceline_and_wrap_info(self, space, source=None):
""" search for the line of input that caused the error and then return
a wrapped tuple that can be used to construct a wrapped SyntaxError.
Optionally pass source, to get better error messages for the case where
this instance was constructed without a source line (.text
attribute)"""
text = self.text
if text is None and source is not None and self.lineno:
lines = source.splitlines(True)
text = lines[self.lineno - 1]
w_filename = space.newtext_or_none(self.filename)
w_text = space.newtext_or_none(text)
return space.newtuple([space.newtext(self.msg),
space.newtuple([w_filename,
space.newint(self.lineno),
space.newint(self.offset),
w_text,
space.newint(self.lastlineno)])])
Interesting ๐
anyone here can help me with coding problems tomorrow 8-10 am??
[9:29 AM]
coding questions like dynamic programming ,graph and trees
This is Pypy's btw
possibly relevant:
https://github.com/python/cpython/blob/v3.10.0rc1/Objects/exceptions.c#L1474-L1522
https://github.com/python/cpython/blob/v3.10.0rc1/Parser/tokenizer.c#L1121-L1149
https://github.com/python/cpython/blob/v3.10.0rc1/Parser/pegen.h#L175-L182
but i see other things that look syntax error related scattered throughout these C files
If you want help with an ongoing exam, that's not going to work here.
!rule 8
8. Do not help with ongoing exams. When helping with homework, help people learn how to do the assignment without doing it for them.
Hello, is there a way to perform sanity checks before pytest goes about traversing through file directory to find test files? In other words, is there a "setup" file that pytest reads and runs before starting to look for test files?
Why do we have mutability? Can't we just treat stuff like lists
Also how does py know that the obj is mutable
Is there a way to call the value of a variable instead of the variable?
kinda in C when you set it equal to the mem address at that time, instead of the variable pointing to that address
I know that much but y tho
basicaly it takes that value at the mem address, copies it, then sets a new pointer to it
no, that is impossible
it is an invalid operation on a lot of objects
or well, just about all objects
except maybe a string
a = 69
b = {"a":a}
print(b["a"])

a string you say? maybe I can do some type conversions
you still can't do it
it would be skipping calling the object creation protocol, which would break a lot of things
as well as forcing the objects to share various metadata which is mutable
I see, I appreciate the information. Always happy to learn.
Why do we have mutability? Can't we just treat stuff like lists
Also how does py know that the obj is mutable

def solver():
for y in range(9):
for x in range(9):
if grid[y][x] == 0:
for n in range(1, 10):
if possible(y, x, n):
grid[y][x] = n
solver()
grid[y][x] = 0
return
global griddy
print(grid[0]) # stupid ass python .. it works here.
griddy = grid[0]
return
solver()
print(griddy) #
the value printed the 2nd time doesn't match the 1st time.
if you put the base case at the top you won't have a problem
oh this is not #algos-and-data-structs
go to #algos-and-data-structs and we can talk about a sudoku solver
I rewrote it already, I was just wondering if python had a different way for the future.
I moved my other functions inside. Not what I wanted to do, but its working, meh.
i pinged you in the correct channel, this is not the correct channel
i just found https://pypistats.org/top <- very curious stats! especially the proportions by python version are very insightful
PyPI Download Stats
#2 python version for botocore is 2.7 sigh
and 3.7 apparently is the most popular one for 3
Is the precedence of operations in python same as math's
why is botocore so popular of all things? is it because amazon downloads it in every lambda function or something stupid like that?
it follows PEMDAS more or less, but imo it's still good practice to use parens for visual clarity whenever possible
!e ```python
print(62 + 22)
@paper echo :white_check_mark: Your eval job has completed with return code 0.
16
yeah I think most of the stats like package downloads don't realistically reflect the general usage of the language because automated tools will pull them at a rate orders of magnitude larger than normal users
all the other ones make sense, e.g. colorama i think is a dependency of ipython
maybe botocore reflects usage of the aws cli
probably, yes
im surprised that its so apparently dominated by a single tool
i'm just as surprised
botocore, urllib3, s3transfer, idna, colorama, boto3, click
also, why 2.7?
maybe there are huge deployments on old red hat systems that have 2.7 with backported security patches or something like that
ah.. that would make sense
does s3 itself still ship with 2.7?
maybe s3 images come with the aws cli pre-installed running on 2.7
it says 2.7 and 3.4
combined with automated tools that would explain things
could it be that tools like that are used on alexa devices?
first signs that IoT finally is taking off?
automated tools finally dominating man-made platforms ^^
How come I've never known about botocore?
What's it for?
Oh I see now, that's interesting
that's an interesting possibility, i'm still surprised that the deps for a single tool so clearly dominate pypi on daily, weekly, and all-time stats
there must be a truly astronomical number of clients using the aws sdk
my sentiment exactly ๐
because it's an "internal" support library that you don't need to interact with..
it sounds like a niche, but the numbers are staggering
i only know about it from reading the boto3 docs
nobody uses it directly, it's a dep of boto3
yeah
like urllib3, it's not weird if you've never "heard of" urllib3
20 is surprisingly high if anything
i expected this to be dominated entirely by "ops" libraries
Yeah, or like Certifi, Colorama which are big too
It seems like pretty much all libraries require those haha
well, colorama is right there on top
typing-extensions is weird
maybe we can infer what kind of clients are using those libs by looking at the daily downloads
hm.. not really any significant difference apparent for me
i assume that's the aws sdk using type annotations on 3.6/3.7
there are some things worth backporting on 3.8 now too
even 3.9
i was looking for those stats to determine which python versions are worth supporting.. turns out 3.9 isn't even on the horizon for most :p
3.7 would be the one that has the most impact these days, i guess
the yearly survey should be more indicative of that
although I guess that would be skewed more to the higher versions as I think people who regularly update and watch the development more closely are also more likely to know about the survey
!e
Why do dataclasses allow overriding attributes like this?
from dataclasses import dataclass
@dataclass
class Foo:
x: int
y: str
@dataclass
class Bar(Foo):
x: list
print(Bar(1, "aaa"))
print(Bar.__dataclass_fields__)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
001 | Bar(x=1, y='aaa')
002 | {'x': Field(name='x',type=<class 'list'>,default=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,default_factory=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD), 'y': Field(name='y',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,default_factory=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)}
Protocols
Why not?
that breaks subtyping somewhat, no?
def function(foo: Foo) -> int:
return foo.x + 42
bar: Bar = ...
print(function(bar))
I mean, from a typehint perspective, not the runtime
So now they're invariant?
hm??
Foo and Bar
wdym by 'invariant'?
hello can someone help with something?
is it simple or difficult?
@trail elk
This channel is for meta-discussions about Python. If you have need help with something specific, you should see #โ๏ฝhow-to-get-help and claim a help channel
not really meta
well it's supposed to be i guess, when we're not talking type hints ๐
well, this is a meta-discussion about python ๐
but a discussion about python isn't meta :p
this is a meta-discussion about Python Discord
but yeah, I might have used the term incorrectly
I hope the meaning was clear though
...and this is a meta-discussion about this discussion
mypy catches the error though (expression has type "List[Any]", base class "Foo" defined the type as "int")
is it not possible to break the subtype relationship in normal classes as well?
!e Please someone send me God ```py
import inspect
from typing import Optional, get_args
def test(
val: Optional[int]
) -> None:
pass
for name, value in inspect.signature(test).parameters.items():
print(name, get_args(value.annotation)[-1] is None)
@elder blade :white_check_mark: Your eval job has completed with return code 0.
val False
Hm, pylance allows this
what's wrong?
It's False
!e Please someone send me God ```py
import inspect
from typing import Optional, get_args
def test(
val: Optional[int]
) -> None:
pass
for name, value in inspect.signature(test).parameters.items():
print(name, get_args(value.annotation)[-1] is type(None))
@elder blade :white_check_mark: Your eval job has completed with return code 0.
val True
@paper echo thanks for telling me about all that unicode normalization stuff and giving me the resources last time :D i finally understood NFC/D/KC/KD (although the compatibility is still a bit confusing lol)
today i broke a quiz app because i used a base char + combining char instead of a precomposed char on an answer lol... someone isn't normalizing their unicode inputs ;)
hah, nice!
being a unicode wizard is a good skill
it's very important for data-unfucking
yep lol
you just have to know the core concepts
also understanding what utf-8 is and how it is/isn't related to unicode, if you don't already
and knowing about unicode character classes can be helpful too, the 3rd-party regex library supports them
!pypi regex
re is stdlib and faster, regex is 3rd party and slower but has more features
regex isn't always slower, for example it prevents catastrophic backtracking (most of the times)
yeah, i still got tons of stuff to work through, i'm only scratching the surface... but i know about basic normalization now, so that's great
also, someone's message just got nuked (by pgp?)
interesting, i didn't realize this
it also supports a timeout
i think google's re2 is specifically designed to be safe against "regex attacks"
but i can't get it to build on macos ๐คทโโ๏ธ
I know the discussion is 2h old, but what the heck. Regular regex engines uses a DSF pattern, making them subject to catastrophic backtracking (O(n^2) runtime, for example with .*.*). RE2 on the other end will explore every possibility at the same time, making the execution time pretty much consistent. It does mean it is slower for well designed regexes, but it also means it can accept arbitrary regexes and run them without problems without turning into another https://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016
What's the correct* way to type annotate __init__ methods?
As somehow even without a return, calling them returns an instance of the class
@white nexus No, calling __init__ doesn't return an instance of the class.
Callind __new__ does.
I think mypy and pyright accept not annotating the return type of __init__ at all
then what is __new__?
how are they different
because uh, my inits are currently annotated with the class ๐
!eval
class Logging:
def __init__(self) -> None:
print("the instance has already been created and now I need to 'initialize' it")
def __new__(cls) -> "Logging":
print(f"i'm about to create an instance using the class {cls}")
return super().__new__(cls)
l = Logging()
@naive saddle :white_check_mark: Your eval job has completed with return code 0.
001 | i'm about to create an instance using the class <class '__main__.Logging'>
002 | the instance has already been created and now I need to 'initialize it'
there isn't really any magic in __init__, it really doesn't return anything
it already gets an object that calling the class would return in its self argument
__new__ on the other hand is quite magic and easy to mess up ๐
.bm
...why do I have a ghost mention now
sorry didn't notice it had been answered
You can edit your message with ~~ on both sides to make it strike-through
That's what I usually do as to not cause ghost pings haha
What's the dunder called during slicing?
it passes a slice to getitem
Or a tuple I suppose, not sure how exactly the slice is passed when it's sliced with tuples
ah it doesn't create a tuple with 1,:, but getitem receives (1, slice(None, None, None))
Ah, thanks!
What do you all think would be some "advanced" projects
I'm trying to generate a list of beginner, intermediate, and advanced projects
for a possible command for sir lancebot
but I've never really ventured into that territory so i wouldn't know
i don't think such a command would be very helpful. it'd just spawn questions like "how do i know i'm advanced" and the likes. plus, we already have !projects. also, #community-meta ?
If it sent one of each idea, then you could look at the ideas to see which you think you could achieve.
Hm, fair point.
I was just considering it because I thought it would be nice to have a single idea because (this is an assumption, correct me if I'm wrong) I feel like most people don't really look through the link of !projects, so I thought just a single idea would be nice
And yeah I'll head over to community meta
mypy supports omitting the annotation on self in methods, but if you really want to do it right, you'd do this:
from typing import TypeVar
ThingT = TypeVar('ThingT', bound='Thing')
class Thing:
def __init__(self: ThingT, x: int, y: str) -> None:
self.x = x
self.y = y
this way subclasses can all use the same ThingT annotation and it will all get inferred correctly
this is important for e.g. class methods
from typing import Type, TypeVar
ThingT = TypeVar('ThingT', bound='Thing')
class Thing:
def __init__(self: ThingT, x: int, y: str) -> None:
self.x = x
self.y = y
@classmethod
def from_tuple(cls: Type[ThingT], tup: tuple[int, str]) -> ThingT:
return cls(*tup)
why that rather than string annotations?
you need the typevar to support subclassing correctly
eg```py
class Thing:
def init(self: "Thing", x: int, y: str) -> None:
self.x = x
self.y = y
@classmethod
def from_tuple(cls: "Thing", tup: tuple[int, str]) -> "Thing":
return cls(*tup)
fixed2*
oh
if you have a subclass of Thing, then that subclass from_tuple method will have the wrong annotation
e.g. if you have SpecialThing(Thing), SpecialThing.from_tuple will still be marked as returning Thing, not SpecialThing
that's not usually what you want
Would the typevar properly handle subclasses?
yeah, but most of the time i just omit annotation on self/cls anyway
with bound=, yes @peak spoke
Self works, though, doesn't it?
what's Self? i don't see it in typing
looks like naw
yeah, and a pretty useful thing too
freaking automatic deleting command invokcations sorry
Then add @final
Are these the same?
with open(...) as f:
f.write('blah blah blah\n')
print('blah blah blah', stream=f)
i'd like to plot continuous wavelets (i'd use pyplot.matshow(coef, fignum=1, aspect="auto") in jupyter) but in pyqtgraph instead, anyone know how to do that?
i'd expect there exist subtle differences, but i couldn't put my finger on it
I think print calls flush
what does flush do?
so much for my toilet joke.
TLDR python buffers output
it flushes the output when it finds a newline i think?
They should act the same
print will only flush when you pass in the kwarg, otherwise the buffering is left to the stream (stdout on newlines, files were whatever)
The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Since printed arguments are converted to text strings, print() cannot be used with binary mode file objects. For these, use file.write(...) instead.
Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.
Well, print will do the newline in a separate write if the end kwarg is not removed
there's the subtle difference - byte vs str
could make a difference with threads
is there a better channel to ask about plotting with pyqtgraph? ^^
maybe #data-science-and-ml ? they do a lot of graphing
#user-interfaces may also work
ty
random thing that could be PEPed: there should be infinite ints in python
what would be the use case?
what can't you do with float("inf")?
some APIs only accept ints, not float
how would they accept infinity then ๐ค
int("inf")? ๐
no idea, but i stumbled over that problem a couple of times, passing in None doesn't work either because it doesn't compare
Is there a case where it has to be an int but infinity makes sense? For example if it only does comparisons the api should accept any (real) numeric type
well, my latest encounter was with versions
testing against Version to be more concrete
Version only can deal with ints, but i don't want to test any actual int that users might choose, but it still needs to have valid comparisons
what's a Version?
from packaging.version import Version
it might be feasible to do it as a sibling of math.inf
like math.int_inf
and int("inf") would return that singleton
just an idea
That might be problematic at the C API level and in the C implementation
You would need a special pyobject that isn't an int and add a special case to every int operation
I agree it would be useful but I think it's probably considered not worth it since you can cast to float to compare with inf
Is there even a standard for integers?
You don't have to cast to float at all actually
I know there's a standard for floats which says there should be an infinite one
!e ```py
print(int(float('inf')))
@elder blade :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | OverflowError: cannot convert float infinity to integer
!e ```py
print(21024 < float('inf'))
float(21024)
@spice pecan :x: Your eval job has completed with return code 1.
001 | True
002 | Traceback (most recent call last):
003 | File "<string>", line 2, in <module>
004 | OverflowError: int too large to convert to float
Yeah that's what I thought
So there's no need for a special inf that is an int
You can just use the float one with ints that are outside of float range
i mean, it's probably not that difficult to just subclass int and write your own inf
In [2]: class Inf(int):
...: def __gt__(self, other):
...: return other is not self
...:
...: def __add__(self, other):
...: return self
...:
...: def __sub__(self, other):
...: return NAN if other is self else self
...:
...: def __lt__(self, other):
...: return False
...:
...: ...
...:
In [3]: INF = Inf()
In [4]: INF < 3
Out[4]: False
In [5]: INF > 10
Out[5]: True
In [6]: INF > 11
Out[6]: True
I mean internally. Can you compare ints and float inf in C?
If im initialising a whole bunch of instances of a class, but the class only has state, no functionality, do i use a dataclass or is it gonna kill performance
if the performance/footprint is a concern I'd use a named tuple
I think the fetching of attrs will be a bit slower because it has to go through the itemgetter, but instantiating is going to be faster and the instances themselves are going to be smaller
you can also use attrs
is it possible to make a 3d scatter plot with pandas
Does anyone know how to shuffle a list until a certain condition is met?
I went to a help channel, new to the Discord! Sorry guys
More things about perf, do fstrings carry overhead, does it cost more to have a regular string be f string, ie
f"name"
# compared to
"name"
they'll both be saved as code constants
Okies, time to bring some consistency to this code i guess
Very odd ask: Does anyone know of a very small python module that has an entry point? I want to test that a particular machine can pip install something and execute it's entry point and I want that package to be as small as possible and platform agnostic. Anyone have any suggestions?
could always make one perhaps
What are some small python packages that have entry points?
There doesn't seem to be a great way to search that in pypi
Just make one yourself, all it needs is an init file and a main file afaik
making your own requires publishing to pypi in this case
which is.. not the end of the world?
if you just mean python -m package, all you need is a __main__.py file in the package and it will work
afaik it can even be a namespace package
$ pip install certifi
Collecting certifi
Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
|โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ| 145 kB 4.5 MB/s
Installing collected packages: certifi
Successfully installed certifi-2021.5.30
$ python -m certifi
.../site-packages/certifi/cacert.pem
started from the top of this list and kept going until i found one matching the requirement :> https://pypistats.org/top
PyPI Download Stats
well yes, python recognizes it as a tuple so * is allowed lol
but you're unpacking nothing, so only the second list [] gets into the tuple
yes
lol, check #esoteric-python for some more unpacking nightmare that i posted
Didn't know about this. Thanks! Very helpful ๐
what is the difference between a wheel's console script and scripts found in .data/scripts/?
An example of this is in https://pypi.org/project/s3cmd/
Is there documentation for these "data" scripts?
Hello, I am using ctypes to call the windows api "bitblt" but I noticed it takes almost 10ms to respond
But in c++ its sub 1ms
What's going on here? I should be calling the samr APIs directlf
I am trying to install a package from a private index (say package A) but have package A's dependencies be installed from pypi. I think there is some recent change in how pip handles this.
I previously had
pip install --index-url https://isprivate.com --extra-index-url=https://pypi.org/simple/ A
however that is installing package A from pypi, not the private repo :/
i would think use a proxy to forward from the private index
i can't believe i've never discovered this before
so apparently you can assign to slicings of lists (only with step value of 1, though)... i guess their __setitem__ allows it
which means...
>>> (a:=[])[:] = range(100)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, blah blah blah result truncated, 99]
```~~*who needs list comps*~~ ||\s||
๐ค that's just a = [*range(100)], right?
you can assign with steps:
In [1]: my_list = list(range(10))
In [2]: my_list[::2] = range(5)
In [3]: my_list
Out[3]: [0, 1, 1, 3, 2, 5, 3, 7, 4, 9]
Hi guys, does anyone happen to know of any code templates for onboarding patreon customers to a telegram channel and discord server? I'm not really sure where to start I'm too new to this.
No those are just for use in the code repo
They aren't any standard part of the distribution package
Where do you even see ./data/scripts?
Swap index-url and extra-index-url
I'll give that a try; I implemented a workaround, but you think it should go something along the lines of pip install --index-url https://privateindex A --extra-index-url pypi
Is it possible to generate locked requirements files using https://github.com/pypa/pipenv without having to install modules? Can I maintain the pip-compile requirements.in -o requirements.txt pattern?
ah yes, sorry, i meant that with step you can only do same length
lmao, that's what i subsequently realized, i was using too many steps lol
Hey @unkempt rock!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
no, that's what you already had but in a different order. i'm saying do this:
pip install --extra-index-url=https://privateindex pkg-a
what if a different version of pkg-a is also on pypi?
pip-compile is a good tool, and yes one of its advantages is that the "lockfile" it generates can be read by pip without any additional tooling for other developers
i think --extra-index-url will take precedence?
good question
Iโm looking for a way to generate a requirements file for different environments without needing to be on that environment. Ie. Generate requirements for windows from a Linux machine
@ivanst0 It doesn't. The indexes are treated equally.
https://github.com/pypa/pip/issues/8606#issuecomment-665554122
the order might be arbitrary even
and it seems like overall there isn't really any conclusion
yeah, that's what I came up against... I figured out a decent workaround, the private package (pkg-a) only has one dependency, which I wanted to grab from pypi anyway, so I'm manually installing that dependency first...
mirroring pypi with devpi might be the best long-term solution
then when I install pkg-a, specifying the private repo, it sees the dependencies are there and it's fine...
@mint dock the saga continues ... https://github.com/pypa/pip/issues/10156
yup, am reading that now ๐
good question, i don't think pip-compile currently supports cross-platform. maybe a good question for their issue tracker
I came from there ๐ they do not. You need to compile requirements for the environment in the environment
ah, that's a bummer
i wonder why, just lack of effort/interest?
related: i was talking to webknjaz on #pypa irc recently, they suggested treating the pip-compile output as a "constraints" file rather than a "requirements" file, so you'd do something like this:
pip-compile -o requirements.lock requirements.in
pip install -r requirements.in -c requirements.lock
i didn't even know pip constraints files were a thing
but there's also apparently a bug in pip where constraints files don't work right if they have hashes in them
so ๐คทโโ๏ธ
hello
what to do if I cannot write a project in Python, but I have been studying it for 8 months
what do you mean "write a project"?
can u copy ur code and send
study it again and its develop a project not write
ok
Why does strings have to be immutable?
They generally don't. But it makes some things easier:
- if strings were mutable, they couldn't be hashable, i.e. they couldn't be used as dictionary keys, which is, well, a big problem, since Python is built on top of dictionaries keyed by strings in many places
- it allows for some optimizations (for example, if you return a constant string from a function, it doesn't have to be recreated every time you call the function)
- programs with immutable values are generally easier to understand and write
Then why do we have mutable stuff? 
Some languages do operate almost exclusively with immutable data (like Clojure and Haskell).
Mutable data structures often perform better, and they are easier to implement. It's also a familiar approach from other languages.

and, well, some programs are easier to understand if you mutate stuff.
ultimately you can't avoid mutability, otherwise your program wouldn't literally do anything
Did the first ever comp language use mutability

Nvm
It isn't related now. thanks for info!
At first, there were no high level as we know them. People used to program in machine language, which is directly understood by a CPU. At that level, you can't do without mutation.

i strongly doubt that, since you could simply copy your ds for every operation
you have to be mutating something, writing to stdout, writing to a db, etc
that depends very much on the definition of "mutating"
if you write something for the first time on a tape, you mutate it once and never again
if that bit was set once before, it most definitely is mutated, with either definition
but i'm saying that setting a bit shouldn't count as "mutating", thus any write-once datastructure shouldn't count as mutable.. and you can do anything with a write-once datastructure, as long as you have enough space
Final applies to any name to indicate it shouldn't be reassigned, Literal is an annotation that only the passed literal values can be used
write-once datastructures often are simpler to reason about, that's the main benefit
i'm saying "write-once" now in place of "mutable", for clarity
of course, such datastructures are extremely wasteful most often
it's possible to reduce waste by using diff-tricks and only care about the actual changes, but then it can become even more difficult to reason about than mutable datastructures
the direction would be towards document-databases etc
sometimes it's not about whether mutation actually occurs (because it always does, @ a processor level), but whether the user can perform mutation
for example...in languages like Python and Java, which are relatively big on mutation, there's a difference between value equality (==) and reference equality (is)
you can probably use a github action somehow
i.e. i use one here
and it can build with pyinstaller. then upload the zips to my release page
that's just a test. but it can do all 3 environments. so having it do a pip freeze instead would be easy
tfw unicode
# NOTE: Technically this doesn't cover everything. There's
# a hard-coded list of additional codepoints, and NFKC
# normalization is applied before matching. See:
# https://docs.python.org/3/reference/lexical_analysis.html#identifiers
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
py_identifier_pattern_start = r"[_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}]"
py_identifier_pattern_continue = r"[_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}]"
py_identifier_pattern = fr"{py_pattern_start}{py_pattern_continue}*"
py_module_pattern = fr"{py_identifier_pattern}(?:\.{py_identifier_pattern})*"
py_entrypoint_pattern = fr"{py_module_pattern}:{py_identifier_pattern}"
eaiser to read imo:
py_identifier_start_chars = [
'_',
'\p{Lu}',
'\p{Ll}',
'\p{Lt}',
'\p{Lm}',
'\p{Lo}',
'\p{Nl}',
]
py_identifier_continue_chars = [
*py_identifier_start_chars,
'\p{Mn}',
'\p{Mc}',
'\p{Nd}',
'\p{Pc}',
]
py_identifier_pattern_start = "[" + "".join(py_identifier_start_chars) + "]"
py_identifier_pattern_continue = "[" + "".join(py_identifier_continue_chars) + "]"
py_identifier_pattern = fr"{py_pattern_start}{py_pattern_continue}*"
py_module_pattern = fr"{py_identifier_pattern}(?:\.{py_identifier_pattern})*"
py_entrypoint_pattern = fr"{py_module_pattern}:{py_identifier_pattern}"
gah forgot r on all those strings
/'\\p/ s/'/r'/
when you just get lazy and use lark
i'm confused on the last part - xid_start and xid_continue have an additional definition, that is, characters from id_start and id_continue should be in id_start id_continue* (which i don't understand) after NFKC normalization
ecma javascript regex for jsonschema
jsonschema either MUST's or SHOULD's that the regex is ecma
my interpretation of it was that NFKC normalization is applied before matching against id_start id_continue*
that's said separately, "All identifiers are converted into the normal form NFKC while parsing; comparison of identifiers is based on NFKC."
but the thing in the lexical definition wasn't that
all characters in id_start whose NFKC normalization is in "id_start xid_continue*"
how does a char's nfkc be in another pattern
it doesn't make sense
is that ebnf within ebnf...
it's this crucial difference that separates id_start from xid_start (the latter is used in identifier's definition), but i can't understand it
oh
hm
i think it's accounting for the possibility that the decomposed form could "spill over" into xid_contiue
i'm not sure if it's possible for that spillover to persist after re-composing
well, after you nfkc'd the spill over, it'd just be one precomposed char, so it'd be xid_start
this is the kind of thing where i wish someone left a note as to why
lol yeah same
if only i knew c, perhaps i can dig into the lexer code or whatever controls this

nothing like hard-coding 300 lines of C in a triple quoted string
so they actually use unicodedata.normalize in the parser generator https://github.com/python/cpython/blob/main/Parser/pegen.c#L106-L123
who knows
i'm 3 layers deep into yak shaving right now, i have to cut it off here
lol
making a jsonschema for pyproject.toml tool sections, so i can generate setup.cfg and tox.ini files from pyproject.toml
because there's no spec for either yet and i figured i can at least slap one on the internet somewhere and the devs of setuptools and tox can decide to use it or not
@paper echo here is something for you ๐
>>> np = use("numpy", version="1.21.2", hashes={'b5e8590b9245803c849e09bae070a8e1ff444f45e3f0bed558dd722119eea724'}, modes=use.auto_install)
Collecting numpy==1.21.2
Using cached numpy-1.21.2-cp39-cp39-win_amd64.whl (14.0 MB)
Installing collected packages: numpy
Attempting uninstall: numpy
Found existing installation: numpy 1.21.2
Successfully uninstalled numpy-1.21.2
ERROR: Could not install packages due to an OSError: [WinError 5] Zugriff verweigert: 'C:\\Users\\micro\\.justuse-python\\venv\\numpy\\1.21.2\\Lib\\site-packages\\~umpy\\.libs\\libopenblas.XWYDX2IKJW2NMTWSFYNGFUWKQU3LYTCZ.gfortran-win_amd64.dll'
Check the permissions.
<numpy>:112: UserWarning: The NumPy module was reloaded (imported a second time). This can in some cases result in small but subtle issues and is discouraged.
exec(compile(code, f"<{name}>", "exec"), mod.__dict__)
>>> np.__version__
'1.21.2'
>>> exit()
PS F:\Dropbox (Privat)\code\justuse\src> python
Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.__version__
'1.19.3'
not ideal yet ๐
but the pieces are starting to fall into place
two different numpy versions in the same environment, one public, one private
not viable in the same process yet, though thanks to some weird caching on numpy's part
It's an advanced joke ๐
Doesn't matter if it is about python or not, please don't post random memes here
ok sry
That's pretty damn cool
๐
"only installing packages is missing, but we'll figure it out, shouldn't be too hard" - young, naive me, a few months ago
how does that work?
I sort of recall there's some way to prevent pip from installing to a temp folder then copying to the final location
--no-cache-dir
perfect, thanks
!e ```py
import sys
d = {}
for n in range(10000):
d[n] = None
print(sys.getsizeof(d))
for n in range(10000):
del d[n]
print(sys.getsizeof(d))```
@sand goblet :white_check_mark: Your eval job has completed with return code 0.
001 | 295000
002 | 295000
This suggests that dictionaries donโt decrease in size. But:
!e ```py
import sys
d = {}
for n in range(10):
d[n] = None
print(sys.getsizeof(d))
for n in range(10000):
del d[0]
d[0] = None
print(sys.getsizeof(d))```
@sand goblet :white_check_mark: Your eval job has completed with return code 0.
001 | 360
002 | 640
How does it not linearly increase in size here even though the consecutively filled array should be building up a bunch of empty space? If it never decreases in size.
Does it only account for the size of the hashed into array, not the consecutively filled array?
getsizeof only returns the size of the object, not the contents. To get the size of the dict as it grows/shrinks you'd need to collect the size of the objects within too
I wrote this to help track the size of payloads going out-bound in an api. Seems to work decently (it's missing a few bytes here and there I think)
def sizeof(obj: Union[Dict[str, Any], List[Any], Tuple[Any, ...]]) -> int:
"""Return total size in bytes of object (included nested)"""
size_of = 0
for val in obj.values() if isinstance(obj, dict) else obj:
nested = isinstance(val, (dict, list, tuple))
size_of += sizeof(val) if nested else sys.getsizeof(val)
return size_of
I suppose if you really wanted to be simple (and the dict was serializable) you could just json.dumps it and get the char count of the string.
Things I only think of when talking about what I've thought of 
But it showed growth in the first example
I think that it shows how many bytes the underlying array is using
But yeah, in the second example, it doesnโt increase in size beyond 640
Actually, I wonder why it doesnโt stay at 360
Does it only decrease the size of the consecutively filled array, and it never decreases the size of the hashed into array?
Deleting an entry from a dict leaves a placeholder in its place. I think that's all you're observing there
And it only decreases the size of the consecutively filled array?
But not the other one?
Because it makes sense that the hashed into array wouldnโt build up memory on the 2nd example since it keeps hashing to the same space
If thatโs what you meant by placeholder
I mean that, after you do del d[0], the hash table bucket that previously stored the value now stores a placeholder that says "there used to be a value here but now there isn't".
Yeah
And then it gets put back in that same spot
But what about the other array? That one it just resizes to a smaller size when thereโs too much empty space?
But the same thing isnโt done with the hash table array?
The same thing is done with the hash table array, but deleted entries aren't empty space. They hold placeholders.
PyCon 2010: The Mighty Dictionary
Presented by Brandon Craig Rhodes
Note that a lot has changed since 2010. Dicts now work pretty differently, which is why they now preserve insertion order
oh, neat
So it canโt get rid of dummy slots for some reason?
I was imagining that it would just go through the whole table and rehash everything into a smaller one once there were too many
It could do that, but since rehashing every item is expensive and slow, it doesn't want to
As in it just never ever does it?
It does it when the table grows too large
The deleted entries take up space, so eventually if you keep adding then deleting then adding then deleting, it uses up enough space that it decides it must resize and rehash everything. At that point it might allocate a smaller array for the hash table than it started with, if most slots are filled with "deleted" placeholders.
But it didnโt do it after 1 million things deleted
!e ```py
import sys
d = {}
for n in range(100000):
d[n] = None
print(sys.getsizeof(d))
for n in range(100000):
del d[n]
print(sys.getsizeof(d))```
@sand goblet :white_check_mark: Your eval job has completed with return code 0.
001 | 5242968
002 | 5242968
Right, it would do it when it needs more space.
The shrinking would happen on the path for inserting an key into the hash table, not on the path for deleting a key from it.
Give me a moment, I'll point you to the resize code...
Would that end up making it have problems finding things?
I think maybe thatโs why it canโt do that.
Nvm, it seems like it doesnโt do that, the comment says dummy slots can be refilled.
https://github.com/python/cpython/blob/main/Objects/dictobject.c#L1082-L1093 is a useful comment
Objects/dictobject.c lines 1082 to 1093
/*
Restructure the table by allocating a new table and reinserting all
items again. When entries have been deleted, the new table may
actually be smaller than the old one.
If a table is split (its keys and hashes are shared, its values are not),
then the values are temporarily copied into the table, it is resized as
a combined table, then the me_value slots in the old table are NULLed out.
After resizing a table is always combined,
but can be resplit by make_keys_shared().
*/
static int
dictresize(PyDictObject *mp, uint8_t log2_newsize)```
When is that seen? I tried filling a dict, deleting everything from it, and filling it again, but it never changed its size after the initial filling
Well, I'm having trouble finding this code, so I'll try to explain. The dict is resized when the number of free buckets falls below since threshold (expressed as some percentage of the table size). That's hardcoded to be 2/3rds of the hash table size: https://github.com/python/cpython/blob/main/Objects/dictobject.c#L374-L385
Objects/dictobject.c lines 374 to 385
/* USABLE_FRACTION is the maximum dictionary load.
* Increasing this ratio makes dictionaries more dense resulting in more
* collisions. Decreasing it improves sparseness at the expense of spreading
* indices over more cache lines and at the cost of total memory consumed.
*
* USABLE_FRACTION must obey the following:
* (0 < USABLE_FRACTION(n) < n) for all n >= 2
*
* USABLE_FRACTION should be quick to calculate.
* Fractions around 1/2 to 2/3 seem to work well in practice.
*/
#define USABLE_FRACTION(n) (((n) << 1)/3)```
So at the point where an insertion would push the dictionary load over 2/3rds of slots occupied, it will resize. For this, dummy (previously used) slots and active slots count as used, empty (never used) slots don't.
When you insert 10k items into the table, it reaches some size, at some load factor less than 2/3rds. Deleting those items changes neither the size nor the load factor - it just replaces active slots with dummy ones. Reinserting the same keys again (or ones that hash to the same slots) doesn't change the size or the load factor - the dummy slots just transition back to active.
But, inserting other values that hash to different slots increases the load factor by transitioning more slots to active from empty, and that can cause a resize. And if it does, the table can shrink.
!e ```py
import sys
d = {}
for n in range(10000):
d[n] = None
print(sys.getsizeof(d))
for n in range(10000):
del d[n]
start_size = sys.getsizeof(d)
print(start_size)
for n in range(10000):
d[n] = None
size_now = sys.getsizeof(d)
if size_now != start_size:
print(n, size_now)
break```
@sand goblet :white_check_mark: Your eval job has completed with return code 0.
001 | 295000
002 | 295000
003 | 922 73816
I wonder why it decreased here even though itโs reinserting the same values
Hm. I must have something wrong, then. But it does show that the resize is happening in the insert path and not the delete path, at least
Yeah
I tried it with other multiples of 10 and it didnโt show it
So that was confusing
But I guess itโs just because itโs hard to get it to be at the right size to trigger it by just picking random sizes like that
So replacing the dummy slots with slots with NoneType apparently decreases size?
does NoneType contain less bytes than a dummy slot?
or a singular byte
Is NoneType just one byte i'm guessing?
Or is that irrelevant to the question at all
This isn't counting the size of the objects in the table at all. They're totally irrelevant. It's only counting the size of the table itself, not the objects referenced by that table
What about the consecutively filled array?
Could it be because itโs resizing that?
But not the hash table array?
It's possible that it's got something to do with that, yeah.
!e ```py
import sys
d = {}
print("initial size:", sys.getsizeof(d))
d[0] = None
print("size with 1:", sys.getsizeof(d))
for n in range(10000):
d[n] = None
print(sys.getsizeof(d))
for n in range(10000):
del d[n]
start_size = sys.getsizeof(d)
print(start_size)
for n in range(10000):
d[0] = None
size_now = sys.getsizeof(d)
if size_now != start_size:
print(n, size_now)
start_size = size_now
del d[0]```
@sand goblet :white_check_mark: Your eval job has completed with return code 0.
001 | initial size: 64
002 | size with 1: 232
003 | 295000
004 | 295000
005 | 922 232
So itโs because itโs also keeping track of how much empty space is in the consecutively filled array?
And a resize can also get triggered if that one builds up too much empty space
https://github.com/amogorkon/justuse/blob/main/src/use/use.py is the long answer ^^
the short answer
use("name") delegates to use_str(name), which checks/registers to sqlite registry, makes sure that version and hash are given, checks pypi for the artifact and makes sure that it's supported on the current platform, (then should pull the artifact from a P2P network and then) delegates the installation to pip as a subprocess, then loads the module, applies aspects to it and wraps it in a ProxyModule for further functionality
easy peasy
i'd say the main function for the installation alone is
def _load_venv_mod(package_name, version) -> ModuleType:
venv_root = _venv_root(package_name, version)
pkg_path = _venv_pkg_path(package_name, version)
venv_bin = venv_root / "bin"
python_exe = Path(sys.executable).name
current_path = os.environ.get("PATH")
venv_path_var = f"{venv_bin}{os.path.pathsep}{current_path}"
if not venv_bin.exists() or not pkg_path.exists():
check_output(
[python_exe, "-m", "venv", "--system-site-packages", venv_root],
encoding="UTF-8",
)
for p in venv_root.rglob("**/python.exe"):
venv_bin = Path(p).parent
python_exe = "python.exe"
pip_args = (
venv_bin / python_exe,
"-m",
"pip",
"--no-python-version-warning",
"--disable-pip-version-check",
"--no-color",
"install",
"--progress-bar",
"ascii",
"--prefer-binary",
"--force-reinstall",
"--exists-action",
"b",
"--only-binary",
":all:",
"--no-build-isolation",
"--no-use-pep517",
"--no-compile",
"--no-warn-script-location",
"--no-warn-conflicts",
f"{package_name}=={version}",
)
...
...
if _venv_is_win():
output = run(
["cmd.exe", "/C", "set", f"PATH={venv_path_var}", "&", *pip_args],
encoding="UTF-8",
stderr=sys.stderr,
)
else:
output = run(
["env", f"PATH={venv_path_var}", *pip_args],
encoding="UTF-8",
stderr=sys.stderr,
)
log.debug("pip subprocess output=%r", output)
orig_cwd = Path.cwd()
try:
os.chdir(pkg_path)
entry_points = _find_entry_point(package_name, version)
for pkg_prefix, entry_module_path in entry_points:
path = entry_module_path.absolute()
with open(path, "rb") as f:
return _extracted_from__load_venv_mod_54(f, package_name, pkg_prefix, path)
finally:
os.chdir(orig_cwd)
hey guys, what's the best way to make a decorator class that accepts optional arguments? my current approach is using a function which, when keyword args are supplied to it, creates a new class that is a subclass of my original decorator class with the kwarg as a free variable
is there a more efficient approach than creating a new class everytime i decorate?
my current code:```py
def squarefunction(
function: Optional[Callable[..., Any]] = None,
*, no_verify: bool = False,
):
"""Decorate a function to become a SqaureFunction instead."""
if function is not None: # if deco is invoked in the "normal" way
return SquareFunction(function, no_verify)
class SquareFunctionDecoWrapper(SquareFunction):
def __init__(self, func):
super().__init__(func, no_verify)
return SquareFunctionDecoWrapper
```where SquareFunction is my original deco
WAIT A DAMN MIN-
I CAN JUST USE A FUNCTION
BRUH
def squarefunction(
function: Optional[Callable[..., Any]] = None,
*, no_verify: bool = False,
):
"""Decorate a function to become a SqaureFunction instead."""
if function is not None: # if deco is invoked in the "normal" way
return SquareFunction(function, no_verify)
def decorator(func):
return SquareFunction(func, no_verify)
return decorator
```lesssgo this works
You usually do this: ```py
def squarefunction(
function: Optional[Callable[..., Any]] = None,
*, no_verify: bool = False,
):
"""Decorate a function to become a SqaureFunction instead."""
def decorator(func):
return SquareFunction(func, no_verify)
if function is not None: # if deco is invoked in the "normal" way
return decorator(function)
return decorator
oh, but what's the efficiency difference? without early exiting, it would create a new function object every single time
if it's negligible, then yeah, this way is more readable
That's a fair argument, but this decorator is only used whenever you're actually starting your application (when defining the function where this is used)
It should be negligible
hm, true
It starts to make more sense when your decorator function is more complex than instantiating a class
alright then! yeah, i remember a decorator tutorial i saw a while ago using this exact same format
yep, i'm only using it so my decorator can accept args
thanks!
nested functions in python are negligible at runtime, because they only allocate a function object and store the code object on it
https://github.com/Objectivitix/dunder-magic/blob/main/squarefunction.py and it's finished!
rejoice, as functions invoked with parentheses are no more.
introducing... SQUARE FUNCTIONS!
example:```py
@squarefunction
def func(a, b, *, c):
print(a, b, c)
func(1, 2, c=3) no no no
func[1, 2, "c":3] # this is the way
it has support for parameter verification, instance methods, arbitrary amount of args, and more!
one parenthesis requires 2 keys to write (shift + 9), one square brackets require 1. this is clearly a win.
lmao ๐คฃ but keyword arguments become a bit more inefficient, taking three additional keys (' * 2, shift + ; as opposed to just =)
but it forces you to use square brackets anyways :D
also, congrats on getting mod, @visual shadow!
Level of cursed:
Empty program[๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ฆ๐ฆ๐ฆ] Python with braces
lmao, that's a 7 on the fix error cursed scale, i'm proud of myself
could you subclass set to make a {} function? ๐
how would that work? func{x} would be invalid syntax no matter what
hmm.. probably need some AST transform to make it work
func{x} wouldn't parse to AST tho
func@{ ... } would work, though
but the args would have no order, though
and no kwargs
Could look at the bytecode to get order at least
yeah, there wouldn't be a good kwarg representation like in the case of using subscription syntax (where i used slices)
Ok, so something like this:py for _ in range(n): del some_dict[0] some_dict[0] = None
Isnโt actually O(n), right? Itโs actually O(n * size_of_dict) because it needs to keep resizing the consecutively filled array?
So using OrderedDict instead wouldnโt just be more efficient, it would actually make the time complexity lower?
the best thing you can do is to measure it
put it in a func, measure the time for n up to 1000000 or so, plot it
there's not really a substitute for measuring things
and there's not really a substitute to plotting those things
especially runtimes can be wildly non-linear
Alright, Iโll try to measure it
over n times, you're just removing the key 0 and adding it back in, right? Didn't your earlier snippet just demonstrate this doesn't cause a resize on just removing 1 item?
No itโs ok, I should do it myself
It ended up resizing it after it was inserted the 922nd time
And it seems like it does it because of space built up in the consecutively filled array.
Because in the hash table array, it should just keep getting placed in the same slot and not build up any extra space there
I learned matplotlib a while ago, so Iโll have to relearn it
Unless I feel lazy and just use timeit
I mean hopefully there will be enough of a time difference for it to be clear that the dict size makes a difference
Or are you talking about this?
how did you determine it was resized? I don't see why it would ever resize in that loop
It showed it being resized here
weird
and I can reproduce that result.... I wonder why that happens?
it doesn't happen in python2
Itโs because of the consecutively filled array it started using
I think
I think that if you did the same thing before 3.6 then it wouldnโt do that
Since it wasnโt using that 2nd array back then
But after 3.6, when you do that, that array keeps on building up more and more empty space. So now it ends up needing to resize due to that
@sand goblet but that implies that the consecutively filled array is pre-allocated for more than 900 elements, which doesn't seem right.
oh, because it's 10,000 elements to begin with
I see
Yeah
And I guess maybe that 922nd time was where it ran out of space and had to resize
yes, if you start with 100 elements, it resizes at 70. with 1000, it's 365
from timeit import timeit
setup_f = """
def f(d):
for _ in range(100000000):
del d[0]
d[0] = None
"""
print("starting")
for n in range(9):
setup = f"d = dict.fromkeys(range({10**n}))\n" + setup_f
print(
f"size of 10**{n}:",
timeit(setup=setup, stmt="f(d)", number=10)
)
print("done")```
output: starting size of 10**0: 134.0548474 size of 10**1: 152.4461155 size of 10**2: 151.38745489999997 size of 10**3: 166.49713710000003 size of 10**4: 169.86379470000008 size of 10**5: 224.49477790000003 size of 10**6: 232.23714919999998 size of 10**7: 236.50534930000003 size of 10**8: 322.2628354000001 done
it doesn't seem linear
I don't get how
It seems like it should take more time since it needs to resize a bigger array, but it's not increasing linearly
I rewrote it to check the size after running f, and itโs not like itโs never decreasing the size
The smaller dicts end at reasonable sizes
So idk
hash tables are O(1) for insertions, removals, and lookups - that's the entire reason we use them.
As the array gets larger, resizes become more expensive but less frequent, making it amortized constant time.
I donโt get how does it make it amortized in this situation
the array itself is larger, since it has more keys in it
and when the array is resized is based on how full it's become (meaning that it takes more insertions before the larger array needs to get resized)
@sand goblet this is how lists have O(1) append(): resizing is less frequent as the list gets larger
and the new array's size is a multiple of the original array's size - it grows by 50% or so - preserving the property that resizes continue to be less frequent each time it needs to resize
Iโm imagining the way it would work is:
at the size of 10, it would go up to maybe around 20 used spaces, and then resize down to something closer to 10 again, and keep doing that in a loop.
at the size of 100, it would go up to maybe around 200 used spaces, and then resize down to something closer to 100 again, and keep doing that in a loop.
at the size of 1000, it would go up to maybe around 2000 used spaces, and then resize down to something closer to 1000 again, and keep doing that in a loop.
Something along those lines, except not with exactly the same numbers
Because itโs staying at the same number of used spaces
taking that and running with it:
At 10 it would need to resize every 10 insertions, so 10,000,000 times.
At 100 it would need to resize every 100 insertions, so 1,000,000 times.
At 1000 it would need to resize every 1000 insertions, so 100,000 times.
The resizes become more expensive but less frequent.
actually, i'm thinking of completely yeeting this into a full-blown project, with staticsquaremethods, classsquaremethods, squareproperties, squarefunctools, etc etc
i need to make my squarefunction fully compatible with everything :muhahahahha:
That would be pretty cool, I wish I had as good as an understanding as you on OOP haha
Dude, I've seen you manipulating initial namespaces with prepare and yeeting __annotations__, you probably have the same amount of knowledge on dunder methods and OOP concepts as I do
Theoretically, we understand OOP. But putting it into practical use and actually using it is a whole other topic lmao... I personnally sometimes struggle with that
I suppose, but what is set_name, isnt it something with descriptors? Iโm probably just not understanding your code because I am usually bad at reading tons of lines till I mess around with it and see how it works
Your code is very well documented tho
people who follow PEP8 all the time and not just when it is required >>>>>
Ah yes, it tells the descr object what name it got assigned to in the class and also the class itself in which it got assigned
Lol thanks
Well, in my code, I had to get the qualname of the class for the standard method repr behaviour
Ah
Tomorrow I'll clean it up a bit, I tjink usinh the underlyinh finctipns and metjoda are better
Btw, that was a test to see what happens when i type on mobile wiyhout correvting myself lmao
Bruh i make way too many spellinv errors because my svreen is small
LOL
https://pastebin.com/0mULnLqD why ma websocket is not working (404 establishing connection)
@nova iris OHH I get it
class Foo:
pass
class B:
var = Foo() # calls Foo.__set_name__
B.var # calls Foo.__get__
variable = B.var # calls Foo.__set__
You got it, it calls Foo.__set_name__(obj, B, "var")
You were right before you edited
Inst.descr = value
can some one help me solving a examination code?
Why does putting list around groupby consume the inner iterators here?
!e ```py
from itertools import groupby
for k, g in list(groupby("AAABBCDDDD")):
print(k, list(g))
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
001 | A []
002 | B []
003 | C []
004 | D []
!e it works fine without it
```py
from itertools import groupby
for k, g in groupby("AAABBCDDDD"):
print(k, list(g))
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
001 | A ['A', 'A', 'A']
002 | B ['B', 'B']
003 | C ['C']
004 | D ['D', 'D', 'D', 'D']
Seems like it reuses the same 2nd argument:
In [24]: from itertools import groupby
In [25]: g = groupby("AAABBCDDDD")
In [26]: h, i = next(g)
In [27]: j, k = next(g)
In [28]: list(i)
Out[28]: []
_grouper object, hmmm:
In [31]: k
Out[31]: <itertools._grouper at 0x21d51bc4eb0>
In [32]: k?
Type: _grouper
String form: <itertools._grouper object at 0x0000021D51BC4EB0>
Docstring: <no docstring>
In [33]: from itertools import _grouper
In [34]: _grouper?
Init signature: _grouper(self, /, *args, **kwargs)
Docstring: <no docstring>
Type: type
Subclasses:
The returned group is itself an iterator that shares the underlying iterable with groupby(). Because the source is shared, when the groupby() object is advanced, the previous group is no longer visible.
Curious 
so you'd have to [(k, list(g)) for k, g in groupby("AAABBCDDDD"))] to list it properly
yeah
this is the wrong channel for your question, #algos-and-data-structs or #โ๏ฝhow-to-get-help
np
Right now I am browsing the web to find a solution/lib to detect real time sounds from a stream. Anyone has some good recommendations?
As an example detect the classic Mario jump sound from a stream input
that sounds like a simple case of convolution and thresholding
in which file of python directory can i find built in functions
like max min etc
if it is in scripts folder
๐
like you can access built in modules in Scripts folder
which file?
that's in cpython
damn knew it
What is the middleman Involved in using cython functions in python ๐ค
Or are they used directly in the script
no idea what you mean
Groupby also only does consecutive groups, so you either need to sort before grouping or do a 2nd pass over the groups and chain them together
cpython is not cython
cpython is the reference implementation of python, cython is an another language on top of python
ah
Yes, Cython is a Python-compatible language, which compiles to C code that uses the CPython API
And yes, a lot of Python modules and functions are written in C in the reference implementation CPython, not in Python itself, either for technical necessity or for performance
im only like a day late but i have another cursed thing
....__new__(....__class__).__str__()
[๐ง๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ]
brb
>>> class DataDescr:
def __get__(self, instance, owner=None):
return instance.__yeet
def __set__(self, instance, value):
instance.__yeet = value
>>> class Foo:
lol = DataDescr()
>>> f = Foo()
>>> f.lol
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
f.lol
File "<pyshell#5>", line 3, in __get__
return instance.__yeet
AttributeError: 'Foo' object has no attribute '_DataDescr__yeet'
>>> f.lol = 3
>>> f.lol
3
>>> Foo.lol = 4
>>> f.lol
4
>>> Foo.lol
4
```no, during instance value setting `__set__` is called, but not during class attribute retrieval
also, my idle's indents are messed up so :P
ah yes, the classic quadruple dot
I messed around with prepare a bit
typechecking weird looking dataclass
!e
from __future__ import annotations
import builtins
class Attrs(dict):
"""Dictionary that takes over namespace."""
def __init__(self, dct: dict):
self.values_dct = dct
def __missing__(self, key):
if key not in self.values_dct.keys() and not key.startswith('__'):
if (result := getattr(builtins, key, None)) is None:
try:
result = globals()[key]
except KeyError:
result = locals()[key]
if not isinstance(self.values_dct.get(
(var_name := list(self.keys())[-1])), result):
raise TypeError(f"{var_name} is not of the type {key!r}")
elif key.startswith('__'):
raise KeyError
value = self.values_dct.get(key)
self[key] = value
return self[key]
class AttrDefinition(type):
"""Metaclass for setting the namespace to a special dictionary"""
def __prepare__(*args, **kwargs):
return Attrs(kwargs)
class TypeCheckingDataclass(metaclass=AttrDefinition):
"""No-op for allowing kwargs to be passed into the namespace"""
def __init_subclass__(cls, **kwargs):
pass
class Foo(TypeCheckingDataclass, x=2, y=2):
(x, int)
(y, int)
print(Foo.x)
class Bar(TypeCheckingDataclass, x=2, y=2):
(x, str)
(y, int)
@surreal sun :x: Your eval job has completed with return code 1.
001 | 2
002 | Traceback (most recent call last):
003 | File "<string>", line 46, in <module>
004 | File "<string>", line 47, in Bar
005 | File "<string>", line 20, in __missing__
006 | TypeError: x is not of the type 'str'
it also works with classes within the file itself, instead of just builtins
(it's SHOULD, and yeah no ECMA implementation exists for most languages, including Python unfortunately.)
The only reason I used class here is to initialize 1 var only so I will be able to use this s3_client everywhere in the class
Then I use the other method scan_bucket with multithreading.
Do you think itโs a good reason to use class?
I am getting really confused with basic design skills & the overall project structure
@worldly ridge likely not, but occasionally it's ok
it's true people don't generally like 1-method classes
the way to think about classes (better than the typical textbook "bundles of state and behavior" which doesn't mean much) are they're for "nouns" -- if you have an important noun in your problem you might have a class
is an "S3BucketEnum" a thing you're likely to say (in english) when describing what your program does (unlikely, so probably it's not a good class, but if your program is super centered around S3 manipulation, maybe)
also if whatever == "protected": protected = True bla bla is a long way to write protected = is_protected == "protected"
i don't see how that s3 client is in any way relevant
so no, i don't see any point in making it a class
it's not used anywhere in that class?
i don't see anyway
maybe somewhere off the screen
if s3_client isn't mutated, having it in that class is pretty moot
i don't get the enum part of that class
possibly the enum is a collection of functions
but then you don't need an extra class..
it's a bit wonky ๐
has someone experience with https://github.com/worldveil/dejavu?
Its a lib to fingerprint songs and recognize them
Thinking about a class like this makes so much different. Thanks! Any suggested book for this kind of stuff?
the private functions use the s3 client on the same class
You get a help channel here #โ๏ฝhow-to-get-help
@worldly ridge let's not bypass our filters
oh sorry
It's much more polite to just ask for more information. That's why we don't allow dumping the link
Understood
@unkempt rock hey, your question is off-topic for this channel. Please see #โ๏ฝhow-to-get-help
grr.. i'd really like a None-aware operator or somesuch
from collections import namedtuple
T = namedtuple("tuple", "name")
d = {"foo": T("foo")}
d["foo"].name
no problem
d.get("foo").name also nice
but now try to access the dict programmatically ๐ฆ
thing = "bar"
d.get(thing).name
=>
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
There's always the python-ideas mailing list where people share possible future ideas for Python
tbh i don't know the ideal solution to this problem
i just know the status quo sucks :p
that's why i'm posting it here, maybe there's some spark of genious
getattr(d["foo"], name)?
I don't understand your point, why not use d[thing].name?
You get a decent error message from it
i don't want an error message, i want to default to None or something else without loads of boilerplate
getattr
getattr(d["foo"], name, None), looks for the attribute name in d["foo"] and defaults to None if there is no name attr iirc
Unless that's not what you're trying to do
i know what it does, but that doesn't cover the KeyError ^^
Ah
you would use getattr(d.get(thing), "name", None)
yeah
then i could also go with "if name in d:", but there really should be a nicer way
maybe something like d[thing]?.name
!e
class NoneAwareDict(dict):
def __matmul__(self, other):
try:
return self[other]
except KeyError:
return None
my_dict = NoneAwareDict()
my_dict['foo'] = 'bar'
print(my_dict['foo'])
print(my_dict@'bar')
print(my_dict['bar'])
@surreal sun :x: Your eval job has completed with return code 1.
001 | bar
002 | None
003 | Traceback (most recent call last):
004 | File "<string>", line 12, in <module>
005 | KeyError: 'bar'
@verbal escarp
Something like that
or if you wanted to, you could try and patch it into the dictionary builtin itself
i somewhat doubt it would fix the attribute error on None in the subsequent lookup
Ah
well that you would have to just deal with that
Because the dictionary just returns the key, it won't handle the value
In [15]: class NoneAttr:
...: __getattribute__ = lambda *_: None
In [16]: class NoneVals(c.UserDict):
...: __missing__ = lambda *_: NoneAttr()
In [17]: from collections import namedtuple
...: T = namedtuple("tuple", "name")
...: d = NoneVals({"foo": T("foo")})
...: d["foo"].name, d['bar'].name
Out[17]: ('foo', None)
``` this is viable if you're sure you're going to be doing an attribute access, but I just wouldn't bother
@verbal escarp there's languages that handle null chaining beautifully
swift has their cool ? operator
how is it handled in those languages?
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."
``` <https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html>
aha, that would be akin to what i suggested, no?
uhhhh, what did you suggest? a null coalescing operator?
oh yeah, it works like that basically. it gives you an optional though
In kotlin you have ?., Null chaining operator, and scope functions,.and a null ternary operator
@verbal escarp if you can write out the python code with null checks explicit etc I can "translate" so you can see
!pep 505
I still can't believe we got pattern matching instead of this
I would love null-aware/null-propagating . for getattr and [] for getitem
I'm less convinced by the null-coalescing ?? operator because we have falsy None, so or works fine 99% of the time
??=is a neat trick but ?. and ?[] were seriously valuable
it's true
I don't even want statement-based pattern matching
time to write Python 4
is localshop still around?
One of the reasons for denying 505 was;
This has been deferred on the basis of the proposed operators being intended to aid traversal of partially populated hierarchical data structures, not for traversal of arbitrary class hierarchies. This is reflected in the fact that none of the other mainstream languages that already offer this syntax have found it worthwhile to support a similar syntax for optional function invocations.
another one was that ? is one of the last available alphanumeric chars for operators
i would want neither, reject modernity, embrace tradition
That's super weird and confusing
So it's not general enough?
Actually optional function invocation is a great idea
Well optional conditional on an argument, not the function itself
And yes there's no syntax for that because it's a lot more complicated
"We have a free operator... let's not use it"
Why is traversing an arbitrary class hierarchy relevant here?
Nobody wants to do that, people want to operate on data without twisting themselves around
Yeah lmao I don't get it
What does traversing a class hierarchy even mean
I don't know it's way too eloquent
what does optional function invocation mean? like 0 or func()?
or 1 or func()
which will call it depending on if it doesn't short circuit?
Oh hold on
You guys misread, I just went back to the doc
That was the reason for rejecting a generic syntax for None-short-circuiting function calls
As in foo?(x) short circuiting on x
So they are saying that they didn't want to over-generalize
Which is why they are suggesting PEP 505 and not some very generic thing that works for all function calls
Or worse, they are shooting down a proposal for foo?() to dispatch on foo
You could make an argument for foo?(), ?., and ?[] all dispatching on their first arguments
Although the semantics of self in method calls would be questionable and inconsistent
But this is very clearly not the PEP deferral reason
It seems like the issue is whether None is special enough to warrant special syntax
I personally think it very obviously is, but ๐คทโโ๏ธ
Hmmm... imagine if you could subclass None? It would break the is None idiom so it wouldn't work in Python
But could have been an interesting language feature
What would be the use of subclassing it?
Custom sentinel values and placeholders, like exceptions
To allow the programmer to distinguish between different kinds of missingness
You could probably place None with a subclassable None using forbidden fruit or just ctypes i think
iirc
more like subclassable Nonetype
Right
I would do that but I don't know the deep depths of ctypes or forbidden fruit lol
Just make your own class then, none doesn't get you anything
Hm, fair
The sentinel pep also looks nice
what sentinel pep?
Sentinel values, don't know the number
The advantage to subclassing NoneType would be that you could "catch" any form of missingness with isinstance(x, NoneType)
Including forms you yourself didn't define or think to include in the check
more kinds of null... sounds scary
Do you want to include cases you didn't define?
Basically making it analogous to Exception
I was bored so I tried to make a rust looking closure
eval isn't very secure though
!e ```py
from future import annotations
from forbiddenfruit import curse
def or(self, other):
if not isinstance(other, str):
raise TypeError
return ClosureFunction(self, other)
curse(list, "or", or)
class BlankSpace:
"""Made for the purpose of looking like a closure"""
def or(self, other):
"""Allowing to look more like a closure"""
return other
class ClosureFunction:
def init(self, params, func):
self.params, self.func = params, func
def __call__(self, *args, **kwargs):
assert len(self.params) == len(args) + len(kwargs)
for value, name in zip(args, self.params):
locals()[name] = value
for param_name, param_value in kwargs.items():
locals()[param_name] = param_value
result = eval(self.func)
return result
ใ
ค= BlankSpace()
cool_func = ใ
ค|['x', 'y', 'z']|"x + y + z"
print(cool_func(1, 2, 3))
@surreal sun :white_check_mark: Your eval job has completed with return code 0.
6
Wait a minute, forbiddenfruit works on snekbox??
what is literals ?
typing.Literal```
A type that can be used to indicate to type checkers that the corresponding variable or function parameter has a value equivalent to the provided literal (or one of several literals). For example:
```py
def validate_simple(data: Any) -> Literal[True]: # always returns True
...
MODE = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: MODE) -> str:
...
open_helper('/some/path', 'r') # Passes type check
open_helper('/other/path', 'typo') # Error in type checker
```...
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
6
\uffa0 : HALFWIDTH HANGUL FILLER - ๏พ
i have two list ,
img_list contains bunch of numpy arrarys
img_ID contains ID
problem : i want Index of 'scissor.png' which is in img_ID how i can access it?
Hi This room is not a help channel. Please see #โ๏ฝhow-to-get-help and claim a help channel.
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
hi
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
{}
On a different note, I read in the PEP505 discussion thread that there is 5 different singletons, which ones? Only None comes to my head
True and False also. Can't immediately think of more.
NotImplemented and Ellipsis too, iirc
ye, None True False NotImplemented Ellipsis are the 5
True False are not singletons, but shhh
what is the singleton to rule them all ? ๐
True and False, at least in CPython implementation, are singletons ๐ค
singleton is a class with a single instance to my knowledge
True and False are two instances of the same class, ergo not a singleton
def python(x):
makes sense, indeed
@flat gazelle I think in this context it means something like "an object which is equal only to itself"
Nicenice
then I have no idea what it means lol
This might be somewhat philosophical but the poster probably just meant True and False as well
Unless someone can think of 2 other ones
probably things you should use is to compare with
but then it's a bit of a tautology, isn't it?
what kind of a definition is based on "should"
What about this: an object you cannot construct in another way. For example, if you do 5 == 5 or bool(42) you get the same object
well, int and str will also share some instances
but IG it is a good enough definition
yeah, but it's not guaranteed
caching can be done by anything (if it doesn't break stuff)
how about just instances of types where python specifies a finite number of instances
that's a better definition
what about just types with a fixed, finite set of instances?
hmmmmmmmmmmmmmmm
well, float has a finite number of instances
they do not, you can have two distinct equal floats
hm wait, it doesn't
yeah yeah, just a finite number of values, the objects might be different
'finite number of instances' is good because it includes enums
well, bool is an enum, conceptually
class enum.Enum```
Base class for creating enumerated constants. See section [Functional API](https://docs.python.org/3.10/library/enum.html#functional-api) for an alternate construction syntax.
!e
from enum import Enum
class Bool(int, Enum):
No = 0
Yes = 1
print(Bool.No, Bool.Yes)
print(Bool.No is Bool.No)
print(Bool.Yes is Bool.Yes)
print(Bool.No.value, Bool.Yes.value)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
001 | Bool.No Bool.Yes
002 | True
003 | True
004 | 0 1
you can click on the embed title to visit the full page
but
it doesn't include object-sentinels
I give it 30 min before we devolve into type theory
N-dimensional ectofibrocardiomorphism
you win
Maybe we should just define the semantics behind is and == and then it will become clear?
is is used when you want to compare objects by identity, == when by value (whatever equality means between these values (wink numpy))
But that is not a useful definition -- it doesn't tell you when you use is and == besides a tautology
Are file writes in python buffered?
Does using an intermediate buffer list instead of writing in a loop give any noticeable perf benefits?
ye, some buffering is done
print does buffering, so I assume yes
import time
for i in range(10):
print(i, end=" ")
time.sleep(0.1)
i realised there's a very useful pattern in func signatures
one positional-only, rest keyword-only
it's quite fascinating how much it simplifies call-chains
Would you still recommend i use a buffer list instead of having a bazillion writes in a loop?
Im processing a lot of text files
did anyone else stumble across that pattern?
will you be surprised by "profile" as an answer? 

I'll get to that eventually, some bugs still holding me back from running the script, was hoping for a clear advantage with buffer lists
@astral gazelle but what are you going to do with the list? writelines?
Right now im joining it into a big string and dumping it in the file with write
ok, that works
sounds like on the order of megabytes