#internals-and-peps

1 messages · Page 153 of 1

swift imp
#

Yes with respect to a custom object that is not founded on some thing with already existing contexts

#

Like what expectations are there for an object that handles paths ?

#

Are there any?

elder blade
# swift imp Are there any?

Yes, since it's an abstraction over a string I would expect that adding two of them together would result in a path inhabiting both

swift imp
#

Honestly I'm surprised they added an operator at all

raven ridge
#

arguably it's an abstraction over a list of strings, rather than an abstraction over a single string (this is where @visual shadow and I disagree)

white nexus
#

in other news

raven ridge
#

but yes, it's an abstraction over either a string or a sequence, depending on how you squint at it, but either way, + is used for concatenation for both strings and sequences

white nexus
#

python2, you never truly took the print statement with you

swift imp
#

They originally wanted to use []

raven ridge
#

that's interesting - I can kinda see the metaphor for that

#

it's "descent"

#

though I wouldn't have thought of that metaphor myself

elder blade
#

Yeah I would actually kind of like that over /

#

Path('/home/user')[Path('Downloads/)]

#

Grab the Downloads folder inside /home/user

raven ridge
#

yeah. Hm. I wouldn't have thought if it, but I sorta like it.

#

but the fact that I wouldn't have thought of it probably does mean it isn't intuitive

feral cedar
#

it's super clunky. compared to either + or even /

swift imp
quasi hound
#

wow that is so weird

#

well windows paths use \ right

#

and unix uses /

elder blade
quasi hound
#

so ig it makes more sense for the latter

elder blade
#

Logically, because programs work with logic, it intuitively makes sense.

quasi hound
#

Path('Users') / Path('me') kinda makes sense but might as well use path.join or whatever

elder blade
raven ridge
#

that makes sense, but the metaphor falls apart a bit with Path("/home")[Path("me/Downloads")]

swift imp
#

So they explicitly didn't inherit from str bc they didn't want to be able to concatenate with a string that wouldn't lead to a valid filepath. So it's almost like they didn't want these things to look or be expected to act like a string in anyway

quasi hound
#

why do you need to index Path('/home') with a Path if you're just making another path? why shouldn't it be just
Path('/home/')['me/Downloads']

elder blade
#
user = Path('/user')

downloads = user['downloads/']

print(downloads['some_text.txt'].read())
quasi hound
#

waste of memory and time typing it out and readability

#

there we go

elder blade
#

lol

gleaming rover
#

@raven ridge how do you feel about Keras using __call__ to represent connecting nodes in a deep learning model graph

elder blade
raven ridge
quasi hound
#

but this is all stupid anyway, can you not just put it into one Path constructor all at once? and if you don't know one of the paths or whatever just use an f-string

raven ridge
gleaming rover
gleaming rover
#

or something, it's been like 2 years

quasi hound
#

layer_c = Dense()(layer_c)

#

hmm

#

jk

gleaming rover
#

so the __call__ of all layers is overloaded to return a new layer connected to self

#

this would create input_layer -> layer_a -> layer_b -> layer_c

elder blade
swift imp
gleaming rover
elder blade
raven ridge
#

I don't have any problem with that - I don't have any particular expectations for what function-call syntax does... I guess I have fewer expectations for what __call__ can do

quasi hound
#

__call__ is generally a bad idea to use from my experience

#

i almost never have really had to use it, prob never

swift imp
raven ridge
raven ridge
gleaming rover
#

so the thing about / in paths

feral cedar
#

it's just not a common "symbol" as + or / or []

gleaming rover
#

indeed / is normally "division", but it's also the separator...so I could see it as being like a DSL

#

i.e. "not as bad" as <<

#

or >>

raven ridge
#

it's also "the" separator on some OS's

swift imp
surreal sun
elder blade
gleaming rover
surreal sun
#

str.mod for example, I believe that was talked about here tho

gleaming rover
#

you literally have things like @<% or something

elder blade
gleaming rover
#

is there really any reason apart from history?

#

it's so WEIRD

swift imp
#

C

gleaming rover
#

which would fall under "history"

quasi hound
#

why was __matmul__ even added

surreal sun
# elder blade Because it looks cool? lol

Well, because of intuitiveness. With paths for example, / is usually the separator in some cases so people might use it as a separator.

It's specific to what's being used

quasi hound
#

couldn't numpy use something that already existed, like oh i don't know __mul__

quasi hound
#

for matrix multiplication

#

why not

gleaming rover
#

because that would be elementwise multiplication

#

this is discussed in the PEP

feral cedar
#

does anything in vanilla py even use matmul

swift imp
quasi hound
#

as someone on here said, @ should be some sort of function composition

gleaming rover
quasi hound
#

makes sense

gleaming rover
quasi hound
#

so they could do ** then maybe

gleaming rover
#

and making * matrix multiplication

quasi hound
#

matrix powers aren't a thing afaik

gleaming rover
#

would probably be weirder

#

because +, -, / would all work elementwise

#

and not *?

elder blade
feral cedar
#

that's element exponentiation

swift imp
quasi hound
#

alright lol

feral cedar
gleaming rover
#

although that is a bit of a math special case

#

compared to the more "basic" elementwise ops

swift imp
#

So in matlab matrix multiplication is * numpy is supposed to be the matlab killer

feral cedar
#

how do they do elementwise?

charred wagon
#

How many ASCII symbols do we even have left to use for new operators? I can only thin of $ and !

swift imp
raven ridge
# gleaming rover is there really any reason apart from history?

well, % used to be the way of formatting strings. It predates all of the others, and is analogous to printf-style format strings in C, which use a % prefix in front of placeholders. It's pretty weird to map that to the % operator, but that formatting did need to be able to accept a tuple, which means the choice is either using some operator for it, or making it a method like "%s, %s!".format("Hello", "world") - I'm guessing the latter was rejected because of its verbosity, and because of how common an operation string formatting is.

elder blade
charred wagon
#

Oh and ?

swift imp
#

Matlab follows matrix syntax

gleaming rover
elder blade
#

Usually you read / and think division - that's your intuition doing that

gleaming rover
#

and I literally tried "/" to concatenate two fragments

gleaming rover
#

and it worked

swift imp
gleaming rover
#

although I can see the force behind +

elder blade
gleaming rover
#

so basically history, no?

elder blade
#

yeah

swift imp
#

Didn't they ban images or it bc u guys have higher ranks

feral cedar
# elder blade

blue you gotta chill with these reaction media, they're huge on mobile

raven ridge
gleaming rover
#

$ isn't used, right

gleaming rover
elder blade
feral cedar
#

didn't they claim some operators for the future? or was that rust

charred wagon
surreal sun
gleaming rover
surreal sun
surreal sun
#

brain fart

charred wagon
#

is it strictly the domain after the @? The email address standard is quite complex

elder blade
surreal sun
#

Idk tbh, mostly just an example

gleaming rover
raven ridge
surreal sun
gleaming rover
#

but isn't the portion after the @ called the "domain"?

gleaming rover
charred wagon
raven ridge
#

` was a circumfix operator

swift imp
#

A what

feral cedar
#

goes around the operand

gleaming rover
#

but I could be wrong about this

charred wagon
#

As in prefix, postfix, infix, circumfix

swift imp
#

New word learned

gleaming rover
#

I think I remember reading that it's not regular

surreal sun
#

TIL

gleaming rover
#

or if not, just that it's really complex (in terms of the regex)

surreal sun
#

I've only heard of prefix postfix and infix so far

#

are there any postfix operators in Python?

gleaming rover
#
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
charred wagon
#

very good and cool. :)

charred wagon
feral cedar
#

? should have been😭

raven ridge
gleaming rover
#

just as monads can be understood simply as monoids in the category of endofunctors

#

🥴

raven ridge
#

or maybe rejects some valid ones?

surreal sun
gleaming rover
surreal sun
#

I really really really wanted none awarenoperators

gleaming rover
#

I'll take your word for it

surreal sun
#

I'm so disappointed

swift imp
#

Nonecoalescing

elder blade
swift imp
surreal sun
native flame
#

re: pathlib using / for joining paths - if i didnt know about it, i would intuitively expect + instead of /, but after looking it up i wouldn't have trouble understanding why it is the way it is (personally i still prefer +)
re: matrix dot product vs elementwise multiplication - i really like how julia (and apparently matlab too) does it, where A op B, like A * B means an operation on the container(?) as a whole, while A .op B, like A .* B means an elementwise operation

swift imp
#

I felt like that pep would take away a lot of readability that people love about python

elder blade
#

At this point !, ? and {} feel so un-pythonic I wouldn't like to ever see them added

surreal sun
elder blade
#

Ah shit you right

swift imp
#

Tough balance

gleaming rover
surreal sun
#

One of my main grudges with Python rn tbh is the import system, mostly because its behind the scenes machinery confuses me, but I'm slowly learning

gleaming rover
#

would be nice to have it like TS, Kotlin (and I think C#?)

surreal sun
#

well, not grudges, more like things I find confusing

swift imp
#

I've never written java

elder blade
#

I like the place None is at, it's not implicit like NULL but not an overly huge deal unless you have a lot of optional attributes (which isn't very pythonic in the first place).

surreal sun
elder blade
raven ridge
#

no

#

Python's is massively more complex than any other language I'm familiar with.

#

part of Python's trend to be dynamic in a way that allows nearly everything to be customized

native flame
# gleaming rover WTF

i find it quite intuitive
maybe i was just not that used to numpy, but i found it very hard to guess which operation was going to be elementwise and which was going to be on the array as a whole

gleaming rover
#

I honestly can't think of many which would give rise to such ambiguity

#

Hadamard product vs matrix product is the only one

native flame
#

matrix multiplication is one of them, obviously
there's no operator for matrix exponentiation, you have to call a function
that tripped me up because i was naively expecting (A ** n) @ v to apply A on v, n times

swift imp
#

From linear algebra if I multiply 2 matrices I would expect that to be matrix multiplication not hadamard product (element wise)

swift imp
native flame
#

no such ambiguity if you have special syntax for elementwise, A .^ n vs A ^ n

raven ridge
#

that seems quite consistent, at least

gleaming rover
#

okay, I suppose this could have other applications

#

e.g. .+ could be "concatenate"?

swift imp
gleaming rover
swift imp
#

It does but it's no different

native flame
#

for vectors its mostly redundant since + and - on the whole vector is the same as elementwise + or -
still, i think it improves readability by better expressing what you're trying to do

gleaming rover
native flame
#

julia as a whole is quite specialcased for numeric computing :P

gleaming rover
#

yeah

#

that's why

native flame
# gleaming rover e.g. `.+` could be "concatenate"?

[a b] is horizontal, [a; b] is vertical and theres a separate method for cat along other dimensions (though i think the newest release you can use n semicolons to represent a cat along the nth dimension)

jolly wedge
#

Guys i need help, its related to flask and ctypes basically. I have a client,server and a hardware.py
Now basically i scan my fingerprint, generate a ISOTemplate from the fingerprint, then match the iso templates and it gives a score. Previously i had it all in one file and, day before i separated it to server and client.
So heres my problem, Everyything works fine if i get the ISOTEmplates directly on server (they are basically stringbuffers) and compare them. But the problem is when i get the stringbuffers on client, and attempt to send it via requests to my server and then do the matching, the matching doesnt work. Something breaks with the ctypes IDK what. Id really appreciate any help. BTW, this is asked on the #help-cake channel, just a little above, please check it out as ive uploaded a bunnnch of screenshots of all the shit ive tried

#

this is the output for the code above

#

@neat basalt thanks for responding btw 😄

flat gazelle
#

C++ Imports are just the C preprocessor before cpp20, and for all it's faults, its really simple

#

Python's insanity in terms of imports is unique, most languages just use file paths, maybe with some extra roots.

grave jolt
#

oh, I didn't realize people were talking about imports specifically

#

yeah, it's a bit cursed

spice pecan
#

But it also allows for things like pythonnet that just import System.Collections.Generic

#

And that's insane

grave jolt
#

@scarlet goblet Can you stop spamming your articles in completely unrelated channels?

stray plinth
#

'''py x = 0'''

#

'''x=0'''

spice pecan
#

You need to use backticks (`), not apostrophes (')

#

Those are usually located on the same key as tilda (~)

white nexus
#

my mind is somewhat blown by this

#

yeah that's cool

#

obvious, but cool

#

saw a method that returned a call of an awaitable function, essentially being an awaitable itself

empty kite
#

How exactly doesmemoryview work? I get that it's supposed to avoid copying data, but don't you have to copy data to get it out of the memoryview? Slicing a memoryview just creates a new one. Suppose:

>>> mv = memoryview(b"abcdef")
>>> mv[0]
97

Does slicing copy the first byte (b"a") here?

>>> mv[1:3]
<memory at 0x000001DEFF21D900>
>>> bytes(_)
b'bc'

To be able to work with a slice of a memoryview, you have to convert it to a bytes object. I'd imagine this copies data out of the memoryview. If so, how and why is memoryview still useful regardless? The only use case I could come up with is when you repeatedly slice a bytes/bytearray object and end up not using every slice afterwards.

quick snow
empty kite
red solar
elder blade
#

Say you want to compare the first two bytes, there's no need to copy the data there - just compare it with the memoryview slice.

empty kite
#

I take it that you don't have to copy data out of the memoryview if you're able to use it in a way that leverages the buffer protocol then. That's probably the whole point of it, I get it now.

When working with binary data, which one is preferable? The linked SO answer mentions struct being able to accept memoryviews

struct.unpack_from("<I", buffer, offset)
mv = memoryview(buffer)
struct.unpack("<I", mv[offset:offset+5])
raven ridge
dapper dome
#

@frosty panther

spring light
#

what's a good formatting provider which follows pep8 and is better than black

astral gazelle
#

What does "better than black" mean, whats wrong with black, also #black-formatter

jovial flame
#

black but with colored diff and default settings for line length prior to wrap

visual shadow
spring light
spice pecan
#

black

naive saddle
spring light
#

hmm lemme try yapf

#

weird why does yapf not change anything, did black just do that already and yapf also wants to do the same?

#

interesting

feral cedar
#

whoulda thunk

spice pecan
#

Black says in its readme that it's PEP8 compliant, so I wouldn't expect another PEP8 linter to change the formatting significantly

white nexus
#

nah, yapf defintely changes stuff

white nexus
astral gazelle
#

Why the importance of being pep8 compliant, the point of a formatter is to be consistent across a team, not exactly to follow some arbitrary rules

elder blade
grave jolt
#

I think the most common deviation is line length

rich cradle
white nexus
#

!pep 8

fallen slateBOT
#
**PEP 8 - Style Guide for Python Code**
Status

Active

Created

05-Jul-2001

Type

Process

white nexus
swift imp
#

So I just used pattern matching for first time. Used to it navigate through decoded json. I really like it, especially the ability to nest patterns but I was left a little short of completely happy due to the way sequence patterns work. It would be cool if you could match if any item in a sequence matches a pattern or if all items in the sequence match a pattern

#

I was trying to do something like

match foo:
   case [*_, {'a' :  str () as bar}, *_] :
      ...

Thinking it would find for me a dictionary with key 'a' whose value is a str and capture it

#

But we can't ignore position

#

I wish they would add something for this

surreal sun
#

Yeah I've encountered the same longing too

feral cedar
#

!e

def hi():
    from math import * 
``` what's the reasoning behind this erroring?
fallen slateBOT
#

@feral cedar :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 | SyntaxError: import * only allowed at module level
pliant tusk
#

because local names inside a function scope are found at compile time and import * dynamically makes names

#

the only way it would work is if it made them globals

feral cedar
#

huh

pliant tusk
#

like py def hi(): from module import foo would work, because the name foo (and the number of items being imported) can be determined at compile time

feral cedar
#

right

spice pecan
#

yeah, local names are determined at compile time, and instead of a string-PyObject* dict, like globals, they're stored in an array and referenced to via index. This makes them faster and that's why you can get a "Variable referenced before initialization" in a function, but not in a module

surreal sun
#

No wonder why the bytecode op name is "LOAD_FAST"

prime estuary
#

In Python 2 this did work, silently downgrading the whole function to non-fast locals - using LOAD_NAME like in module/class scope, and using a dict.

pliant tusk
#

interesting i wonder why that got dropped for python 3

spice pecan
#

I'd assume it has something to do with consistency and reflection

#

If updating the value returned by locals() sometimes updates locals and sometimes doesn't, it's probably not fun to debug

charred wagon
#

Are locals still mutable though?

#

Or is it fixed at compile time?

prime estuary
#

Indeed, silently changing the performance like that is problematic.

quick snow
#

!e

def f():
    locals()["x"] = 42
    print(locals()["x"])
    print(x)
f()
fallen slateBOT
#

@quick snow :x: Your eval job has completed with return code 1.

001 | 42
002 | Traceback (most recent call last):
003 |   File "<string>", line 5, in <module>
004 |   File "<string>", line 4, in f
005 | NameError: name 'x' is not defined
unkempt rock
#

!e isn't there some funny business like that that you can do

def f():
    locals = lambda *_: {"x": 42}
    print(locals()["x"])
    print(x)
f()```
fallen slateBOT
#

@unkempt rock :x: Your eval job has completed with return code 1.

001 | 42
002 | Traceback (most recent call last):
003 |   File "<string>", line 5, in <module>
004 |   File "<string>", line 4, in f
005 | NameError: name 'x' is not defined
unkempt rock
#

weird

quick snow
#

Well that part doesn't surprise me, assigning to the name locals doesn't do anything special

unkempt rock
#

Discovered this very intriguing "anomaly" or pattern if you will from a help channel here.

#

!e

sets = [set(range(i, i + 3)) for i in range(0, 21, 3)]

for s in sets:
    print(s)
fallen slateBOT
#

@unkempt rock :white_check_mark: Your eval job has completed with return code 0.

001 | {0, 1, 2}
002 | {3, 4, 5}
003 | {8, 6, 7}
004 | {9, 10, 11}
005 | {12, 13, 14}
006 | {16, 17, 15}
007 | {18, 19, 20}
unkempt rock
#

How come every third element is out of order

#

So, sets don't preserve order and it makes sense that some are unordered

#

But then how come that every 2 out of 3 are ordered

spice pecan
#

sets are unordered, and any order that happens to be displayed is not to be relied on

spice pecan
unkempt rock
#

This is so weird but also cool. I wanna understand why

#

!e

sets = [set(range(i, i + 10)) for i in range(0, 100, 10)]

for s in sets:
    print(s)
fallen slateBOT
#

@unkempt rock :white_check_mark: Your eval job has completed with return code 0.

001 | {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
002 | {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
003 | {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}
004 | {32, 33, 34, 35, 36, 37, 38, 39, 30, 31}
005 | {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
006 | {50, 51, 52, 53, 54, 55, 56, 57, 58, 59}
007 | {64, 65, 66, 67, 68, 69, 60, 61, 62, 63}
008 | {70, 71, 72, 73, 74, 75, 76, 77, 78, 79}
009 | {80, 81, 82, 83, 84, 85, 86, 87, 88, 89}
010 | {96, 97, 98, 99, 90, 91, 92, 93, 94, 95}
pearl river
#

!e note also:

s = set()
for i in range(20):
    s.add(i)
    print(s, end=" ") 
fallen slateBOT
#

@pearl river :white_check_mark: Your eval job has completed with return code 0.

{0} {0, 1} {0, 1, 2} {0, 1, 2, 3} {0, 1, 2, 3, 4} {0, 1, 2, 3, 4, 5} {0, 1, 2, 3, 4, 5, 6} {0, 1, 2, 3, 4, 5, 6, 7} {0, 1, 2, 3, 4, 5, 6, 7, 8} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} 
pearl river
#

huh, strange, I wanted to show that the order may change when the set resizes

#

but looks like small ints are truly blessed

deft pagoda
#

i think the hashes for small ints are just those ints

pearl river
#

they are

deft pagoda
#

!e

for i in range(10):
    print(hash(i), end=" ")
fallen slateBOT
#

@deft pagoda :white_check_mark: Your eval job has completed with return code 0.

0 1 2 3 4 5 6 7 8 9 
rotund grail
#

!e

fallen slateBOT
#
Command Help

!eval [code]
Can also use: e

*Run Python code and get the results.

This command supports multiple lines of code, including code wrapped inside a formatted code block. Code can be re-evaluated by editing the original message within 10 seconds and clicking the reaction that subsequently appears.

We've done our best to make this sandboxed, but do let us know if you manage to find an issue with it!*

rotund grail
#

e

gaunt trellis
#

e

rotund grail
#

!e

fallen slateBOT
#
Command Help

!eval [code]
Can also use: e

*Run Python code and get the results.

This command supports multiple lines of code, including code wrapped inside a formatted code block. Code can be re-evaluated by editing the original message within 10 seconds and clicking the reaction that subsequently appears.

We've done our best to make this sandboxed, but do let us know if you manage to find an issue with it!*

rotund grail
#

!e
print("Hello this is SNIPER")

fallen slateBOT
#

@rotund grail :white_check_mark: Your eval job has completed with return code 0.

Hello this is SNIPER
feral cedar
pearl river
# feral cedar the hashes are cached so that shouldn't change order

One doesn't follow from the other, no:

{'rjyme'}
{'rjyme', 'lzikw'}
{'pfxua', 'rjyme', 'lzikw'}
{'pfxua', 'dhfno', 'rjyme', 'lzikw'}
{'dhfno', 'pfxua', 'lzikw', 'nqlka', 'rjyme'}
{'dhfno', 'pfxua', 'lzikw', 'nqlka', 'rjyme', 'ygfsn'}
{'dhfno', 'pfxua', 'lzikw', 'mhxsf', 'nqlka', 'rjyme', 'ygfsn'}

here both the absolute and the relative order changes as I add elements, when the set resizes

feral cedar
#

huh..

#

time to read the C ig

pearl river
# feral cedar time to read the C ig

the position in the hash table is basically hash % n, which can and will change when n changes, unless hash<n (and that's why it works for small ints)

feral cedar
#

oh, I knew that 😔

dusk comet
#

!e

s = set()
for i in range(10):
  s.add(i)
  print(s)
fallen slateBOT
#

@dusk comet :white_check_mark: Your eval job has completed with return code 0.

001 | {0}
002 | {0, 1}
003 | {0, 1, 2}
004 | {0, 1, 2, 3}
005 | {0, 1, 2, 3, 4}
006 | {0, 1, 2, 3, 4, 5}
007 | {0, 1, 2, 3, 4, 5, 6}
008 | {0, 1, 2, 3, 4, 5, 6, 7}
009 | {0, 1, 2, 3, 4, 5, 6, 7, 8}
010 | {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
dusk comet
#

!e

s = set()
for i in range(10):
  s.add(str(i))
  print(s)
fallen slateBOT
#

@dusk comet :white_check_mark: Your eval job has completed with return code 0.

001 | {'0'}
002 | {'0', '1'}
003 | {'0', '1', '2'}
004 | {'0', '1', '3', '2'}
005 | {'3', '2', '0', '4', '1'}
006 | {'3', '2', '0', '5', '4', '1'}
007 | {'3', '2', '0', '5', '4', '6', '1'}
008 | {'3', '2', '0', '5', '4', '7', '6', '1'}
009 | {'3', '2', '0', '8', '5', '4', '7', '6', '1'}
010 | {'3', '2', '0', '9', '8', '5', '4', '7', '6', '1'}
sick aurora
#

!eval def f():
locals = lambda *_: {"x": 42}
print(locals()["x"])
print(x)
f()

fallen slateBOT
#

@sick aurora :x: Your eval job has completed with return code 1.

001 | 42
002 | Traceback (most recent call last):
003 |   File "<string>", line 5, in <module>
004 |   File "<string>", line 4, in f
005 | NameError: name 'x' is not defined
unkempt rock
quick snow
#

TL;DR: Hashmaps start with size 8, so the last 3 bits of the hash are relevant.

fallen slateBOT
#

@quick snow :white_check_mark: Your eval job has completed with return code 0.

001 | {0, 1, 2} ['000', '001', '010']
002 | {3, 4, 5} ['011', '100', '101']
003 | {8, 6, 7} ['1000', '110', '111']
004 | {9, 10, 11} ['1001', '1010', '1011']
005 | {12, 13, 14} ['1100', '1101', '1110']
006 | {16, 17, 15} ['10000', '10001', '1111']
007 | {18, 19, 20} ['10010', '10011', '10100']
quick snow
#

!e

sets = [set(range(i, i + 3)) for i in range(0, 21, 3)]

for s in sets:
    print(s, [f"{x:03b}"[-3:] for x in s]) 
fallen slateBOT
#

@quick snow :white_check_mark: Your eval job has completed with return code 0.

001 | {0, 1, 2} ['000', '001', '010']
002 | {3, 4, 5} ['011', '100', '101']
003 | {8, 6, 7} ['000', '110', '111']
004 | {9, 10, 11} ['001', '010', '011']
005 | {12, 13, 14} ['100', '101', '110']
006 | {16, 17, 15} ['000', '001', '111']
007 | {18, 19, 20} ['010', '011', '100']
unkempt rock
#

I would like to read up on mental models people use for Python

#

Basically what pythontutor does, but articles explaining the mechanism behind what Python does internally

#

Much appreciated

surreal sun
#

There's a good book about Python Internals if you want it

#

.rp 1 CPython Internals

neon troutBOT
surreal sun
#

that has the book linked iirc

#

and if you want a free version that still teaches you a decent chunk of it

#

.rp 1 Python Internals

neon troutBOT
surreal sun
#

oh huh

unkempt rock
surreal sun
#

Np

molten kayak
#

is this the new #advanced-discussion ?

white nexus
#

no, its the same advanced discussion just the name is different

molten kayak
#

ah nice

#

i just came across this so im probably being dumb but if stdin is actually a file and to read from it, you read the file, then does that mean user input comes with the overhead of writing to a file?

#

because thats a pretty expensive operation computationally

peak spoke
#

It's file like, usually not an actual file

molten kayak
#

in memory?

peak spoke
#

The streams are also buffered by default so not that huge of a concern even if backed by an actual file

sonic flax
#

man what happened to PEP505

#

The "None-aware attribute access" operator ?. ("maybe dot") evaluates the complete expression if the left hand side evaluates to a value that is not None

#

this part in particular would be so useful

unkempt rock
#

Yup, it would be heh

empty kite
#

Also for type hints. int? instead of Optional[int] or int | None would be so much nicer

grave jolt
#

eh, not much

#

I'd rather the Noneness be more explicit

flat gazelle
#

int | None exists now IIRC

feral cedar
#

i think swift does that

empty kite
flat gazelle
#

and most of the time, you want exceptions so that there is at least some indication of why the value isn't present

feral cedar
#

if only there was a way to hint those 😔

grave jolt
#

you can use your own error values

flat gazelle
#

that's just going to be worse exceptions most of the time

grave jolt
#

and then you realize that your fancy ?-syntax doesn't work for these

#

or for exceptions

#

so now you have a new syntax for something that's already possible, and it still doesn't work

flat gazelle
#

yeah, comprehensive handling of partial values like rust has is really the way to go, but you can't do that in python without changing the whole language.

grave jolt
#

although to be honest, I found a few uses for :=

#

It's handy if you have an elif chain

flat gazelle
#

raku has managed this whole Failures as expressions in a dynamic language quite well, though you rarely check for specific failures in practice.

boreal umbra
flat gazelle
#

you can just variable + variable for variable in [value] for esoteric python.

grave jolt
flat gazelle
#

special casing None doesn't seem like the way to go to me

#

getting better exception handling options would IMO be better

surreal sun
grave jolt
#

just use the Result monad (c) dry-python

surreal sun
#

that or any/all's

grave jolt
flat gazelle
#

let me pattern match on exceptions, give me except try, and a lot of the usecases for None aware operators will just go away.

grave jolt
flat gazelle
#

indeed

boreal umbra
#

I forgot, how is it that super() infers the class and instance arguments? Special parsing, or meta-programming?

flat gazelle
#

I believe special parsing, though you could probably do it with metaprogramming as well.

boreal umbra
#

With metaprogramming, like with inspect? I'm not sure how you could get that information within super.__init__

#

If it's going to be a blessed special case anyway, I don't think the parentheses should be necessary.

#
class super:
    def __init__(self, cls, inst):
        self.cls = cls
        self.inst = inst
    def __getattr__(self, attr):
        for cls in self.cls.__mro__[1:]:
            try:
                return getattr(cls, attr)
            except AttributeError:
                 continue
         raise AttributeError

I assume a pure Python implementation of super would look like this.

flat gazelle
#

it would be cls.__getattribute__(self, attr) I am pretty sure

boreal umbra
#

I don't remember the difference between __getattr__ and __getattribute__

flat gazelle
#

__getattr__ is the fallback

#

it allows you to customise things without special casing things like __class__

#

as well as whatever "real" attributes and method you may have

grave jolt
boreal umbra
grave jolt
#

ah

#

I guess

raven ridge
#

super is a normal-ish class, and you're constructing an instance of it when you call super()

undone hare
#

That sounds so wrong for some reason

#

Is it implemented as some kind of mega wrapper descriptor or something

raven ridge
#

the old-school way of constructing an instance of super was super(StaticClass, self), and what that does is make it so that any attribute lookup on the super() instance returns the corresponding attribute from the first class after StaticClass in the MRO of self

undone hare
#

Hmmmmmmm could you reimplement supper in Python

raven ridge
#

the new-school way is just automatic shorthand for that old-school way - super() expands to super(__class__, <firstarg>) where __class__ is a built-in variable that points to the class a method is statically defined in, and <firstarg> is the first argument to the method that super was called in.

undone hare
#

I feel like it should be possible

raven ridge
#

I think it would be, yes

undone hare
#

Talk idea? PauseChamp

raven ridge
#

could be a good talk. Lots of people find super() confusing, and showing Python code that does the same thing might be illuminating

prime estuary
#

The way it works is that if super is referenced in any method of a class, it creates a __class__ closure cell, and adds that into the function. super() then uses the C equivalent of sys._getframe() to fetch that and also the first parameter.

spring light
#

i always thought super().__init__(avar=avalue) made a self.<var> except in one line

languid iron
# flat gazelle let me pattern match on exceptions, give me `except try`, and a lot of the useca...

just for fun: ```python
import functools

from typing import *

E = TypeVar('E', bound = Exception)

class Error(Generic[E]):
_exc: E
match_args = ('_exc',)

def __init__(self, exc: E):
    self._exc = exc

def __eq__(self, other: Any) -> bool:
    if isinstance(other, __class__):
        other = other._exc

    return (
        isinstance(other, Exception)
        and (self._exc.__class__ == other.__class__)
        and (self._exc.args == other.args)
        )

T = TypeVar('T')
R = TypeVar('R', T, Error)
P = ParamSpec('P')

def with_error_match(func: Callable[P, T]) -> Callable[P, R]:
@functools.wraps(func)
def inner(*args: P.args, **kwargs: P.kwargs) -> R:
try:
return func(*args, **kwargs)
except Exception as exc:
return Error(exc)
return inner

#
>>> def itemgetter(key: Any) -> Callable[P, R]:
...     @with_error_match
...     def itemgetter(value: Sequence[T] | Mapping[Any, T]) -> T:
...         nonlocal key
...         return value[key]
...     return itemgetter
... 
>>> def test_itemgetter(value, /, key):
...     f = itemgetter(key)
...     match f(value):
...         case int(item):
...             print(f'success: {value}[{key!r}] -> {item}')
...         case Error(exc):
...             match exc:
...                 case IndexError() | KeyError():
...                     print(f'failure: {value}[{key!r}]')
...                 case _:
...                     raise exc
... 
>>> test_itemgetter([1, 2, 3], key=1)
success: [1, 2, 3][1] -> 2
>>> test_itemgetter([], key=0)
failure: [][0]
>>> test_itemgetter(dict(foo=1, bar=2), key='bar')
success: {'foo': 1, 'bar': 2}['bar'] -> 2
>>> test_itemgetter(dict(), key='foo')
failure: {}['foo']
>>> test_itemgetter(42, key=0)
Traceback (most recent call last):
  ...
TypeError: 'int' object is not subscriptable
elder blade
spice pecan
#

Before I knew about the specialcased super(), I would constantly make the same mistake of explicitly passing self into the method, i.e. ```py
super().init(self, arg1, arg2, ...)

#

IMO that would be the better option, as I'm not a big fan of specialcasing, but I could see this being not very static/classmethod-friendly

cloud crypt
#

and there isn't something like Error[E] in that annotation

#
AnyException = BaseException

Result = T | Error[E]
AnyResult = Result[T, AnyException]``` perhaps something like this, and then `T` gets mapped to `AnyResult[T]`
#

I really liked the idea of wrapping exceptions into the Error type ngl

pearl river
#

there's a crate package for that IIRC

#

!pypi result

fallen slateBOT
cloud crypt
#

haha, someone caught me on begin rust-y again

#

something like ResultBase with all the methods seems nice, and then Ok (or Value) and Error can derive from it

#

though, full ADTs could be super neat for that

elder blade
elder blade
pearl river
#

specifically, I was doing a lot of similar tasks in worker threads, which may often result in exceptions

#

and I'd catch all exceptions and wrap them into an Error class with the exception inside. That was, the threads always finish without crashing, which was nicer to handle.

cloud crypt
#

indeed

spice pecan
cloud crypt
#

I'd imagine something like ```python
T = TypeVar("T")
E = TypeVar("E", bound=AnyException)

@enum
class Result(Generic[T, E]):
Ok: Case[T]
Error: Case[E]

def unwrap(self) -> T:
    match self:
        case Ok(value):
            return value

        case Error(_):
            ...  # handling

Ok = Result.Ok
Error = Result.Error```

elder blade
spice pecan
#

No, I'm claiming that instead of having a specialcase, making it an actual zero-arg call and explicitly passing self to let it figure out the MRO from the instance passed would be a better solution, IMO

#

Although, now that I think about it, it's probably not going to work the way I want it to work, as there wouldn't be a way to tell what context the call is in

#

Simply looking at the type would never go up the mro unless there's no overload on this type, in which case super wouldn't be used, hmm

spark magnet
spice pecan
#

Having them filled in implicitly just doesn't sit right with me. Thinking about it more, I think I would prefer something like a __super__ or __base__ attribute on an instance with a pre-instantiated super() proxy, though I do understand why not a lot of people would like that

#

It's not a proposal by any means, just heavily biased hindsight

spark magnet
spice pecan
#

Right, so the same issue applies, hrmm

#

Actually, given that the called methods operate on the proxy, it could return another proxy on __super__ access that would be a level higher. I'd have to play around with it a bunch

elder blade
#

Descriptors get a type and an instance

spice pecan
#

The type wouldn't change if the instance passed is the same

#

you'd always get the deepest type available

hidden bloom
#

f

#

hi

#

evryone

#

i have a question

#

i am new here

#

i am tryng to go in some room here

#

where i can tolk

#

but i din t find any rooms to do it

#

there reason is bicouse anyone speaks

#

or it my fault

#

bicouse i am still beginne on discord

#

and i can t find it

#

?

warm junco
surreal sun
#

hmm, so __class_getitem__ exists, but what about __class_instancecheck__? I've seen a lot of people have to make metaclasses to implement an instance check on the class level

#

and same goes for __class_subclasshook__

elder blade
#

I get why __class_getitem__ was added because of its usage with typing.. but I don't think we should add dunders for all uses of metaclasses

surreal sun
#

I've seen instancecheck be quite a common one though implemented onto metaclasses

swift imp
white nexus
#

TFW you need to add optimizations to a python program because 56 seconds is too long

swift imp
#

So can someone explain to me. We cannot pattern match on type?

#

Or you can but you must call the type

spice pecan
#

You have to call the type, yeah

swift imp
#

However this doesn't work on callable

spice pecan
#

otherwise it's a free variable

#

That's because callable isn't a type

swift imp
#

Right

#

But

#

isinstance(lambda x: x, callable) returns true

#

No it doesn't

#

So we can't check if something is callable then

spice pecan
#

callable is a function IIRC

#

That is basically equivalent to hasattr(..., '__call__')

#

(I think)

#

You could use a guard

swift imp
#

That's lame though

spice pecan
#

case x if callable(x)

spice pecan
# swift imp That's lame though

I'm not sure what's used to check types for pm, but there's probably a way to make a class that will pretend to be the type of any callable

swift imp
#

You do

#

Type(kwargs) to see if it's an instance of Type and then if each attribute in kwargs has the subpattern

#

Id probably have to make my own type and override __isinstance__

spice pecan
#

Yeah

swift imp
#

Seems less than ideal

spice pecan
#

typing.Callable runs isinstance checks but doesn't work for pm

#
>>> from typing import Callable
>>> isinstance(lambda: None, Callable)
True
>>> match lambda: None:
...     case Callable():
...             print('Yes')
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: called match pattern must be a type```
swift imp
#

This seems like a major short coming

spice pecan
#

Not really

grave jolt
#

well, the thing is

spice pecan
#

The typing aliases aren't real types IIRC

#

They just use magic

#

(™)

grave jolt
spice pecan
#

Yeah

swift imp
#

There's no base class that all functions and methods inherit from?

spice pecan
#

No

#

Python is duck-typed

#

You just implement the protocol

grave jolt
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

42
spice pecan
#

If you have a __call__ method, you can be called

swift imp
#

What about types.FunctionType or LambdaType`

spice pecan
#

There's no separate LambdaType

grave jolt
#

LambdaType is the same as FunctionType

#

still, a callable object doesn't have to inherit from FunctionType

spice pecan
#

I'm pretty sure FunctionType is an invalid parent

#

!e ```py
class Test(type(lambda: None)): pass

fallen slateBOT
#

@spice pecan :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | TypeError: type 'function' is not an acceptable base type
grave jolt
#

ah lmao

#

makes sense, somewhat

swift imp
#

I don't like this

grave jolt
#

python being duck-typed?

swift imp
#

So I have to either propogate another attribute on the class whose instance state I am trying to match on or do a guard

grave jolt
#

what do you want to do?

spice pecan
#

You can probably use a real type with an isinstance hook

swift imp
#

There's just some things about pattern matching that are really lack luster

spice pecan
#

Pattern matching does feel half-baked

swift imp
#

Like I should just able to check it an attribute is callable

#

It should get a special hook or something being a built in

spice pecan
#

There is

grave jolt
#

what do you mean by "X is callable"?

spice pecan
#

It's named callable and you can run a guard to check it :)

#

If you want to just do case SomeCallableType(): you could use a real type with an isinstance hook

#

Either handmade or collections.abc.Callable

#

!e ```py
from collections.abc import Callable
match print:
case Callable():
print('yes')

fallen slateBOT
#

@spice pecan :white_check_mark: Your eval job has completed with return code 0.

yes
grave jolt
#

Is foo callable?

class Foo:
    def __call__(self, *args, **kwargs):
        raise RuntimError(":^)")

foo = Foo()

if so, then you can use callable (or collections.abc.Callable)

swift imp
#

Oh

swift imp
grave jolt
#

I think you meant to thank GKK

swift imp
#

I find that much better than doing the guard

swift imp
#

The other issue I had with pattern matching is related to sequences

#

I feel like I should be able to match on if any (or all) of the entries in a sequence match some subpattern

#

So say I'm parsing json and I want to find in a list an object (aka dict) that has this pattern {"a"=str(), "b"=5}

#

I feel like that should be possible, right now we have to know absolute position of everything which is cumbersome for matching anything other than the first couple or first last

pearl river
#

hmm, so something like case x if "a" in x and "b" in x and isinstance(x["a"],str) and isinstance(x["b"], int):?

#

I wonder if jmespath can match on a condition like that

swift imp
#

Jmespath?

#

NVM

frank crescent
#
sqlmap.py ...
#

oh a bit old

surreal sun
#

Hmm, just after this discussion about matching exceptions, there is now a thread on matching exceptions in the python mailing list

#

somewhere up here I remember someone talking about matching excpetions

surreal sun
#

Yea around there

#

No wait

#

I recall someone talking about Exceptions somewhere

lusty scroll
#

like this?

def match_exception(e: Exception) -> None:
    match e:
        case FileExistsError():
            print("Does this matter?")
        case TypeError():
            print("It's a TypeError.")
        case Exception():
            print("Some other error.")
        case _:
            raise TypeError(f"Error: {e} is not an error!!!!")
deep bramble
#

How could I check if an attribute in class dictionary from metaclass is a function/callable? I'm trying to decorate all methods in that class, but I need to distinguish the methods from other things ```py
class FooMeta(type):
def new(mcls, name, bases, clsdict):
for name, val in clsdict.items():
# check if val is a method

lusty scroll
#

you only want the methods/functions defined on that class?

deep bramble
#

yeah

#

I also need to exclude static and classmethods, though I think I can just do that with isinstance(val, staticmethod), but I've no idea how would I check if something is a function directly

lusty scroll
#

i believe you can do it

deep bramble
#

I just don't know how would I get the methods (including properties)

deep bramble
#

oh, apparently, there's callable builtin function, how did I miss that

lusty scroll
#

you can use __objclass__ for at least some members

deep bramble
#

so I guess I can just do this```py
for name, val in clsdict.items():
if callable(val) and not isinstance(val, (staticmethod, classmethod)):
...

lusty scroll
#

that will bring in stuff from object i think

deep bramble
#

yeah, but that's fine there's a filter for only specified methods later, I just needed to check that those specified methods are callable

#

though this probably won't catch property but I think isinstance(val, property) will handle that one and there should be some variable under the property class storing the actual function so I can decorate it

lusty scroll
#

!e this kind of works

from inspect import getmembers
from types import WrapperDescriptorType
from typing import Any
def get_own_members(cls: type) -> dict[str, Any]:
  return {
    k:v for k,v in getmembers(cls)
    if not isinstance(v, WrapperDescriptorType)
    and getattr(v, "__objclass__", None) == cls
  }
print(get_own_members(BaseException))
fallen slateBOT
#

@lusty scroll :white_check_mark: Your eval job has completed with return code 0.

{'__cause__': <attribute '__cause__' of 'BaseException' objects>, '__context__': <attribute '__context__' of 'BaseException' objects>, '__reduce__': <method '__reduce__' of 'BaseException' objects>, '__setstate__': <method '__setstate__' of 'BaseException' objects>, '__suppress_context__': <member '__suppress_context__' of 'BaseException' objects>, '__traceback__': <attribute '__traceback__' of 'BaseException' objects>, 'args': <attribute 'args' of 'BaseException' objects>, 'with_traceback': <method 'with_traceback' of 'BaseException' objects>}
deep bramble
#

problem is that I haven't actually made the class object yet, I only have the class dict

lusty scroll
#

oh really? then you can use that (e.g. ns.items()) instead of getmembers(...), I think

#

wait, that won't work

#

what is in the dict?

deep bramble
#

it's the dict from the metaclass

lusty scroll
#

won't it just be the things you're interested in, then? and you could just check if they're callable or have a __get__ attribute, maybe ?

deep bramble
#

!e ```py
class FooMeta(type):
def new(mcls, name, bases, clsdict):
print(clsdict)
clsobj = super().new(mcls, name, bases, clsdict)
return clsobj

class Foo(metaclass=FooMeta):
def my_method(self, x):
print(x)

@staticmethod
def static_m(x):
    print(x)

@property
def my_prop(self):
    return 1
fallen slateBOT
#

@deep bramble :white_check_mark: Your eval job has completed with return code 0.

{'__module__': '__main__', '__qualname__': 'Foo', 'my_method': <function Foo.my_method at 0x7fd832b98ca0>, 'static_m': <staticmethod(<function Foo.static_m at 0x7fd832b98d30>)>, 'my_prop': <property object at 0x7fd832b97d80>}
lusty scroll
#

ah, ok

deep bramble
lusty scroll
#

like __module__

deep bramble
#

yeah but it can also be user-defined ones ```py
class Foo:
X = 5

lusty scroll
#

gotcha

#

does type.__new__() not do the right thing with that namespace dict?

deep bramble
#

well, I'm overriding some of the things in that dict before initializing the class

#

I could probably do it with the class object too but I've already built everything to work with the dict, not the class object

lusty scroll
#

what about using __prepare__ ?

deep bramble
#

how would that help me, I don't need to adjust the initial dict, I need to adjust the values in that dict, but to do that I need those values there. __prepare__ would allow me to add some initial values to the dict, or change it's type to do something special but that's not what I need

lusty scroll
#

it would help to see what kind of adjustments you're making I think

deep bramble
steel solstice
#

whats the logic for checking if you can assign __class__ to a type?

#
class Asset: ...
class Item(Asset): ...
class BaseBackpackItem(Item): ...
class BackpackItem(BaseBackpackItem): ...
class Casket(BackpackItem): ...
```i have a class hierarchy like this (they all have slots), and i want to make a BackpackItem an instance of Casket but when i try and do that i get this error
`TypeError: __class__ assignment: 'Casket' object layout differs from 'BackpackItem'`
surreal sun
quick snow
quick snow
#

And if you really meant changing the class of the class: won't work, because also both classes need to have a common base (i.e. object or type)

steel solstice
#

im not changing the type im changing an instance

#

Casket has an extra slot so id guess that would be the issue?

spark magnet
#

also, slots aren't necessary, so you could drop that too.

steel solstice
#

i dont think its easy to avoid, i want to have a nice api where youre backpack contains backpack items and caskets, caskets are items but have their own storage for more items

spark magnet
#

why does it start as an instance of BackpackItem, and then changes to Casket? Why doesn't it start as Casket?

steel solstice
#

When I fetch the backpack the item starts off as a BackpackItem as I can't tell when it's fetched if it should be a Casket

spark magnet
steel solstice
#

It's fetched from steam using the api and the def index of the item determines if it's a Casket

spark magnet
#

why not wait until you have that index before making the object?

#

even if you do change the class of an instance, you won't get the initialization of the extra attribute a Casket has. It just gets really fiddly to try to change the class.

steel solstice
#

Yeah I add the extra attribute myself

#

I mainly just thought changing the class would be good so I could separate out the functionality for adding/removing items to the casket into a separate type safe place

spark magnet
#

i would strongly advice not changing the class of an instance. it sounds like the opposite of type-safe.

steel solstice
#

Well it's not type safe for me but it is for the end user

spark magnet
#

i don't understand how this makes it type safe. The user only sees the Casket object, right? Does it matter how it got created?

steel solstice
#

Yeah they only see Casket and not the horrific things I had to do to make it

spark magnet
#

ok, so if you make it a different way, it will still be type-safe.

#

and don't use slots, they are rarely needed, and are a headache.

halcyon trail
#

something I was hoping to mess around with in the future

spark magnet
#

before using slots, you should at least clarify why you want to use them.

halcyon trail
#

can't you just set slots=True on a dataclass

#

or attrs

#

that's the way in which I was planning to use them

spark magnet
#

(i realized as i was typing that dataclass/attrs probably made it simple)

halcyon trail
#

ah

#

yeah, to me it seems like very little downside, moderate benefit

#

it does make it a runtime error to add attributes, iirc

#

which from my perspective is generally a good thing

spark magnet
#

i hope your callers weren't hoping to do that 🙂

halcyon trail
#

I am my caller 🙂

#

this is internal code in other words

#

but there are some tricky cases involving dataclass inheritance that I'm not sure if slots will behave properly or not

#

In particular, I have a dataclass that overrides the type of a base dataclass and I'm pretty sure this isn't handled correctly

#

it overrides the type of one of the members, I mean

native flame
#

iirc __slots__ has some confusing behaviour with inheritance too

halcyon trail
#

inheritance with dataclasses is kind of a fraught issue to be fair so I can't blame it too hard

#

i can understand why it's often not supported (though it doesn't prevent it from being annoying)

elder blade
native flame
#

it has some more edge cases, like with multiple inheritance only one of the base classes is allowed to have a non-empty __slots__

steel solstice
#

I'm only using them cause I want them to be immutable

#

And yeah the thing hsb is describing is also a pain

spark magnet
#

(also, do slots make it immutable? It just makes it so you can't add ad-hoc attributes)

steel solstice
#

Yeah that's what I want to prevent

#

Not sure if the two are entirely the same

peak spoke
#

Why does the user creating new attrs on the object matter to you?

#

I'd really only use slots if I had some object that has a very high number of instances, but then it might be better to go out of python

spark magnet
#

I'm also not sure why you want to prevent people making new attributes. what bad thing would happen if they did?

#

and it's their program, so why should you get a vote?

steel solstice
#

I do also have a lot of instances of things (a user can have multiple inventories and they can each have 5000 items each)

spark magnet
#

eh, 5000 isn't so many

swift imp
elder blade
#

Many people host Python scripts on extremely limited VMs

radiant garden
#

Some of those 5000 items can also contain other items, or 5000 in total?

steel solstice
#

They could but for the purposes of this conversation no that's the max

spark magnet
#

it makes sense to use slots if you are running out of memory, true.

#

@steel solstice immutable would mean you couldn't assign a new value to an existing attribute

steel solstice
#

yeah they are meant to be immutable then but enforcing that hurts performance

spark magnet
steel solstice
#

well id have to implement a __setattr__ and it wouldnt be infallible you could use object.__setattr__ (id have to use this to set my own attributes in init)

spark magnet
#

yes, I see what you mean.

halcyon trail
spark magnet
#

yes, but it's not your program? Why not let the caller do what they want?

halcyon trail
#

because, you want to know exactly what's going on with your type, so that when your library operates on an instance of your type, there aren't surprises

#

the whole notion of contracts which underlies, implicitly or explicitly, most of software engineering, works in a certain way

#

You can do XYZ, and when you do those things, I promise to do ABC

#

There's nothing vaguely unreasonable about constraining the scope of what users can do. To be honest, seems more like rationalization for python's lack of features in that area.

#

To be clear; not having said features isn't necessarily the end of the world either, and there's always a lot of care required in deciding what usages are appropriate. But to blanket say it's always wrong seems extreme.

spark magnet
#

you make a good point, but it can also be useful to be able to annotate an object for your own purposes.

halcyon trail
#

Sure; that's precisely why non-intrusive approaches are preferred, and why non-intrusivity is such a highly discussed property of approaches to certain kinds of problems

spark magnet
halcyon trail
#

Exactly one of the issues with inheritance btw

#

Sorry, it seemed that you were very definitely implying such but perhaps that is just my interpretation 🙂

spark magnet
#

to be fair, i was on the "always wrong" side, but I try to ask about things

halcyon trail
#

indeed, that was the impression I had. I think there's a time and a place for locking things down and you can easily go too far. But not allowing the addition of properties to a class isn't really going far, IMHO

#

it's a very basic sort of guarantee

spark magnet
#

but it would only hurt if your code did "for all attributes" somewhere, wouldn't it?

halcyon trail
#

well, at the very least it could hurt for other forms of introspection as well

#

but yeah, that's the obvious way in which adding attributes could break

#

but that's a valid technique obviously. And in larger projects, you can very easily have one person coding up some concrete dataclasses A, B, C, etc while another person is writing generic/introspective code that is supposed to operate on entire types of dataclasses for whatever purpose. that happens even inside my small team.

spark magnet
#

I'll grant you there are failures that could happen from unwanted attributes being added.

halcyon trail
#

The flipside is, when would you ever look at somebody adding ad-hoc attributes to a dataclass and think it's a good idea

#

I'm pretty sure I've never, ever, ever thought that's a good solution to any problem

#

In the age of mypy it's a worse idea than ever; mypy will also flag every single access to your ad hoc attribute as well, you're losing the protections of the type system in checking your work because some instances of that type will have the extra type, some will not

#

just create a new type that holds the library type and any new attributes (or even derived from it)

spark magnet
#

and (to add to your argument): there are other ways to annotate objects if you need to.

#

wait: deriving from it won't help: my new attributes would be on the object, and the base class would still stumble over them.

halcyon trail
#

right, so it depends exactly how you do the inheritance. but at the very least, for example, the library can check the precise type

#

if you inherit from a dataclass into another dataclass, then you can use the schema of the overall object in an organized way

#

But yes, inheritance can in fact also cause many problems, which is why it's become so much more common to take measured approaches to inheritance

#

Even in Java, the father (mother?) of overuse of inheritance, it's often (usually?) recommended that you write classes as final by default and only open them to inheritance if you're designing around it

spark magnet
#

i guess we can add it to the pile of ideas that seemed good at first, then we had to add some guardrails once we realized the dangers.

halcyon trail
#

yes, indeed.

#

but yeah, that's why non-intrusiveness is such a great thing, lets multiple users do things with a type without bothering each other. Another place where inheritance fails pretty hard.
Not having non-intrusive dynamic polymorphism is prob one of the worst things in Kotlin for me, and it's kind of behind the times (compared to Swift, Rust, even Go)

#

But then in Rust you don't have non-intrusive reflection, just intrusive macros... so 🤷‍♂️

elder blade
#

Thoughts on str subclasses? I sometimes feel like I over-use it

#

It's almost like a curse to me that it was allowed in the first place 😅

peak spoke
#

Think the only time I had one was a str enum mixin

#

What do you use them for?

spark magnet
elder blade
fallen slateBOT
#

library/wumpy-models/wumpy/models/emoji.py lines 36 to 47

def __new__(cls, data: Dict[str, Any]) -> 'Reaction':
    id_ = _get_as_snowflake(data, 'id')
    name = data.get('name', '_')
    animated = data.get('animated', False)

    # If id_ is None then it is default Emoji and only consists of the
    # emoji name (which is a unicode eomji).
    return super().__new__(cls, name) if id_ is None else super().__new__(
            cls,
            '<' + ('a' if animated else '') + ':' +
            name + ':' + str(id_) + '>'
        )```
peak spoke
#

may be better off as an attribute then?

elder blade
#

The reason I am asking is because I am considering adding another 😅

#

It's for Discord assets, because they're just a link but I need one method to read them

spark magnet
#

or, a simple class with a __str__ method?

elder blade
#

The thing is that some reactions only have a name so they'd be represented as a string. I thought I'd be easier to deal with if the return value is always a string

#

Because an emoji is more-or-less a nicely formatted string

spark magnet
#

it sounds like a class with a __str__

elder blade
#

Hmm, yeah that's what I had originally

grave jolt
#

I think parsing JSON data in __init__ is a bad idea - makes it harder to re-use this class in other contexts

#

(for example, in tests)

#

wait... why does Emoji subclass from Reaction?

#

I think I'm going to make my own wrapper 👀

spark magnet
elder blade
elder blade
#

I disagree still, the majority of the time you will have all the data represented as the payload?

#

They're just wrappers over that payload, why wouldn't you initialize them with that

grave jolt
elder blade
grave jolt
#

So what's the Emoji class about?

#

or... vice versa

elder blade
grave jolt
#

In your code, Emoji inherits from a Reaction.
I think it's wrong:

  • emojis will still exist even if discord disables reactions
  • emojis exist in context other than reactions, such as in message text
#

I don't think you need to expose the horrors of the Discord API to the library users. It's your job to expose a nice API that makes sense.

#

Ideally, the library should present an interface familiar to a user of Discord ,not the Discord API

#

For example, if you ask an average Discord user if a channel category is a channel, they'll say: "WTF? Are you stupid?"

elder blade
#

Side note: Is this the best place to discuss this? I would like to continue, but not sure if this still applies here

static junco
#

I have a problem

#

Is this the right channel to get help?

raven ridge
white nexus
halcyon trail
#

after upgrading, mypy is giving me tons of "error: Library stubs not installed for pytz" even though I'm running it with --ignore-missing-imports

#

anybody encounter this?

halcyon trail
#

alright thanks

vast cairn
#

hello

#

i would like to learn python but i dont know how

#

could anyone help me

dusk comet
#

this code example wont work
(assuming future annotations is disabled)
variable annotation in function will evaluate expensive_mod, but it isnt imported, so it is NameError

peak spoke
#

Neither of those will evaluate, as explained in the text

unkempt rock
#

this msg to Lu1s, if you don't know how, then first you should clear your this doubt for sure. Go to YouTube, watch some python tutorials and see how this language works, first you will feel it's too easy then you will counter some worth tackling topics loops, fuction, classes and there are so many more. I can't tell all that in text. So, go and check out by yourself gradually your path will become clear how to learn python..

vast cairn
#

ok

#

thank you very much

dusk comet
quick snow
vale arrow
boreal umbra
#

By the same line of thinking that supports whitespace syntax over semicolons and curly braces (which I see as an unmitigated victory for Python), I think it also follows that commas shouldn't be required, either.

flat gazelle
#

It would be ambiguous in many cases, but I am inclined to agree with the idea

boreal umbra
#

implicit string concatenation would have to go away. Nothing else immediately comes to mind.

#

while not ambiguous in terms of the parser, tuples would be less obvious to the eye

peak spoke
#

using only spaces for that seems a bit weird

#

unlike braces, they are used in normal language too

boreal umbra
flat gazelle
#
[1
 -3
]``` list of 1 and -3, or list of -2
boreal umbra
#

ah, good point

surreal sun
#

For import hooks, do you always need to import the import hook that will be doing the work first and then other modules like:

import import_hook

import a
import b
#

and another question, why does __future__ need to imported first on that topic? is it because it's an import hook? or does it enable flags for running other files and stuff like that

peak spoke
#

future does compile and parse time stuff

#

and your import hook has to be run to take effect, so it also needs to be executed (imported) before that

surreal sun
#

I see, thanks

surreal sun
#

and there are some flags by default i.e. print_function

peak spoke
#

depends on what you mean with flags

#

it can do pretty much anything, just has to be implemented

surreal sun
#

Ah, so what does future do when you import say annotations, like a general 'roadmap'

peak spoke
#

I think the features are loaded after it gets the ast

#

then it just checks if the feature is enabled and constructs a string from it instead of doing the whole expression when compiling

quick snow
#

But yes, you need to install the import hook before it can do its import hooking. And __future__ is not a real module, it's special syntax. It does affect parsing (in some cases), which is why it has to be at the very top.

raven ridge
fallen slateBOT
#

@raven ridge :white_check_mark: Your eval job has completed with return code 0.

/usr/local/lib/python3.10/__future__.py
dusk comet
#

!e

from __future__ import annotations
print('annotations' in globals())
print(annotations)
fallen slateBOT
#

@dusk comet :white_check_mark: Your eval job has completed with return code 0.

001 | True
002 | _Feature((3, 7, 0, 'beta', 1), (3, 11, 0, 'alpha', 0), 16777216)
quick snow
quick snow
#

What if we made using global/nonlocal a SyntaxError (or at least SyntaxWarning) when used in a global scope?

dusk comet
#
>>> nonlocal x
  File "<stdin>", line 1
SyntaxError: nonlocal declaration not allowed at module level
sacred yew
#

probably should be a warning for back compat, but i agree

#

see it quite often with newbie (and intermediate) code

quick snow
spice pecan
#

wait, is 3.11 going to finally get None-aware operators? lemon_hyperpleased

native flame
#

👀

quick snow
#

I see the difference in bytecode, but does it actually make a difference? Is there a code example where having or not having it changes something? I guess theoretically LOAD_GLOBAL could be faster since it doesn't have to look at the locals, but since the locals and globals are anyways identical in the global scope I'd think LOAD_NAME doesn't actually look into the same namespace twice there..

quick snow
#

Testing with timeit suggests the opposite, in fact:

In [9]: timeit.timeit(stmt='x += 1', setup='global x; x = 777')
Out[9]: 0.03630954201798886

In [10]: timeit.timeit(stmt='x += 1', setup='x = 777')
Out[10]: 0.01996866599074565
spice pecan
#

I'm pretty sure timeit, compile, etc assume function scope

#

So without global, it'd be STORE_FAST and LOAD_FAST instead of STORE_NAME and LOAD_NAME

#

Although after messing with dis a bunch, it seems that it's not the case

peak spoke
#

They don't assume any scope

spice pecan
#

Yeah, so my theory about why it would be faster doesn't hold up

halcyon trail
#

That would really help

#

They don't go nearly far enough but it would be a great start

#

Though probably it won't go any further :-) but just for common use cases like the default argument dance

prime estuary
#

The opcodes aren't for any actual feature, it's purely an optimisation.

grave jolt
#

yeah, is None is a common check

spice pecan
#

Yeah that's true, I wouldn't be surprised if it were only an optimization for now

#

But it does give me some hope

peak spoke
#

Why do globals need to be a dict? I've spent an hour figuring out why my patch of a framework's dict that was replacing globals was working in one place but not the other until I found out they pass locals in only one eval

#

Both locals and builtins try PyObject_GetItem if they're not dicts, but globals only do PyDict_GetItemWithError which skips my magic

#

This was for eval/exec (which I forgot to mention until the end), eval is documented to only accept a dictionary for globals and LOAD_NAME does assume that

fallen slateBOT
#

Python/ceval.c lines 2992 to 2993

if (v == NULL) {
    v = PyDict_GetItemWithError(GLOBALS(), name);```
peak spoke
#

I mean, definitely feels like an intentional interface at least from eval's side

peak spoke
#

!d eval

fallen slateBOT
#

eval(expression[, globals[, locals]])```
The arguments are a string and optional globals and locals. If provided, *globals* must be a dictionary. If provided, *locals* can be any mapping object.
peak spoke
#

says that it must be a dictionary, I guess it could be ambiguous whether a subclass is a dict (and how it behaves) but it does somewhat make sense after reading

#

!e though this can be confusing

class A(dict):
    def __getitem__(self, item):
        return item
print(eval("invalid", A()))
print(eval("invalid", A(), {}))
fallen slateBOT
#

@peak spoke :x: Your eval job has completed with return code 1.

001 | invalid
002 | Traceback (most recent call last):
003 |   File "<string>", line 5, in <module>
004 |   File "<string>", line 1, in <module>
005 | NameError: name 'invalid' is not defined
acoustic crater
#

what is the byte code for checking if a: vs if len(a) > 0?

frigid trout
# acoustic crater what is the byte code for checking `if a:` vs `if len(a) > 0`?
>>> dis.dis("if a: pass")     
  1           0 LOAD_NAME                0 (a)
              2 POP_JUMP_IF_FALSE        4 (to 8)
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE
        >>    8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> dis.dis("if len(a) > 0: pass")
  1           0 LOAD_NAME                0 (len)
              2 LOAD_NAME                1 (a)
              4 CALL_FUNCTION            1
              6 LOAD_CONST               0 (0)
              8 COMPARE_OP               4 (>)
             10 POP_JUMP_IF_FALSE        8 (to 16)
             12 LOAD_CONST               1 (None)
             14 RETURN_VALUE
        >>   16 LOAD_CONST               1 (None)
             18 RETURN_VALUE
acoustic crater
#

thanks! interesting

dusk comet
#

i think if a: is faster than if len(a):
and if len(a) is faster than if len(a) > 0:

olive marsh
#

Is any one free to review my repo? I made a tool to find unused import inside the python scripts. i think the overall design is vague.

brave badger
#

ah you have, my bad!

surreal sun
#

isn't there a new POP_JUMP_IF_NONE bytecode instr coming soon?

prime estuary
surreal sun
#

ah nice! love these little optimizations

#

Wish we had none aware operators though

spark magnet
#

there are lots of new opcodes coming. RESUME

surreal sun
#

ahh

#

are you gonna rewrite your none aware operator fork thing given the new bytecode instr?

#

!pep 505

fallen slateBOT
#
**PEP 505 - None-aware operators**
Status

Deferred

Python-Version

3.8

Created

18-Sep-2015

Type

Standards Track

surreal sun
#

basically:

#
var = a.b?.c

would be the same as

if a.b is not None:
  var = a.b.c

i believe

#

tbh I like them, maybe I'm just used to how other languages do none aware / null coalescing

#

Also, where can I find the definitions of PyObject_*?

#

like I'm trying to look for where PyObject_IsInstance is defined

#

I found it in abstract.h but it's only the forward declaration

atomic egret
surreal sun
#

intuitively I'd think it'd just be None

atomic egret
#

I mean, if it would be defined, it would have to be None, at which point why bother?

#

that's literally the same as var = a.b.c then

surreal sun
#
Parenthesised expressions are handled by the atom rule (not shown above), which will implicitly terminate the short-circuiting behaviour of the above transformation. For example, (a?.b ?? c).d?.e is evaluated as:

# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
#

how do you search for files in github again

#

found it!

atomic egret
surreal sun
#

Yeah I think that was one of the reasons it was deferred

#

actaully it might not be

#

but I know a lot of people were opposed against PEP 505 (None aware operators) because of how unreadable they are

atomic egret
#

yeah, I'd be too

frigid trout
#

I feel like it shouldn’t be that unreadable as long as you can understand that “?” means that it can be none, especially with how useful non aware operators can be

surreal sun
#

I would personally love it, but I don't think it should be taught in say a beginners tutorial

#

and should probably have some PEP8 guidelines to keep it readable

grave jolt
#

I think having 4 extra if statements will hurt readability worse than ?

sacred yew
grave jolt
atomic egret
#

there's ternary conditional which could be helpful to reduce the clutter, but yeah, none-aware operators would be nicer there. Problem is that people would almost certainly start using it even if it just replaces a single if and I feel like a single if x is None is more readable than ?

grave jolt
#

If a team finds that a single x?.y is worse than an if, they can add a rule to their linter settings

#

you can abuse any kind of syntax

atomic egret
#

yeah, I suppose there could be an option in linters to check for this, still though, I feel like in an average project, especially to beginners, this syntax would be way too confusing to understand and it just introduces extra overhead of looking up what it means

grave jolt
#

well... real-world projects don't employ beginners 🙂

atomic egret
#

yet beginners read the code of real-world projects

grave jolt
#

and you could say this about any new feature

grave jolt
#

? has a different issue though. It will only work for None, and not any other "error value". And it doesn't make handling exceptions easier.

atomic egret
#

hmm, if ? treated an exception in the same way it'd treat None, it would be pretty interesting

#

do other languages with none-aware operators do this?

grave jolt
#

no, but Haskell solved this in a general way in 1990s

grave jolt
#

Rust doesn't have exceptions, so it signals failures with an error type, like Result<i32, SomeErrorType>.

atomic egret
#

yeah, I think I've heard of that, though only very vaguely. Was it something like having a func returning both the actual return value (or none) and an exception value which allowed those functions to basically be chained as long as that other value is not an error value, I may be completely wrong though, I haven't done any haskell, I just heard of something like this somewhere

grave jolt
#

sort of, yeah

#

For example, this is how you could emulate it in Python:

@none_aware
def foo():
    x = yield f()
    c = (yield (yield (yield x.a).b).c)
    return c + 5
#

none_aware looks at the result of each yield. If it's None, it terminates the execution and simply returns None. Otherwise it passes the value back

atomic egret
#

that's interesting

grave jolt
#

well, I wouldn't use this in production 🙂

#

but the idea is there

atomic egret
grave jolt
#

that's sort of how the original coroutines work, actually. so maybe not that bad

atomic egret
#

though it also wouldn't handle exceptions

grave jolt
#

it wouldn't

grave jolt
grave jolt
#

If Python had inline generators, something like ```py
b = none_aware(send (send (send x).a).b)

fallen slateBOT
#

tests/test_basic.py lines 166 to 173

@do
async def point() -> tuple[int, int]:
    await exact("(")
    x = await integer
    await exact(",")
    y = await integer
    await exact(")")
    return (x, y)```
atomic egret
#

@grave jolt my very poor attempt at chaining functions even on exceptions: ```py
from unittest.mock import MagicMock

class ExcChain:
"""Sets up a decorator for a chain of exception aware functions."""

def __init__(self):
    self.sentinel = object()
    self.prev_exc = None
    self.ret = self.sentinel

def reset(self):
    self.prev_exc = None
    self.ret = self.sentinel

def exc_aware(self, func):
    def wrapper(*a, **kw):            
        if self.prev_exc is not None:
            # Return callable mock so that we won't get errors on
            # the actual chain
            return MagicMock()                
        try:
            # If we don't get an exception, store the return value so that we 
            # can get it in the end. Also return it so that the chain can continue
            self.ret = func(*a, **kw)
            return self.ret
        except Exception as exc:
            self.prev_exc = exc
            return MagicMock()
    return wrapper

def get_return(self):
    if self.ret is self.sentinel or self.prev_exc is not None:
        raise ValueError("No return value, chian failed or wasn't not started.")
    return self.ret

exc_chain = ExcChain()

class Foo:
@exc_chain.exc_aware
def z(self):
return 10

class Bar:
@exc_chain.exc_aware
def y(self):
return Foo()

@exc_chain.exc_aware
def x():
print("x called")
return Bar()

@exc_chain.exc_aware
def foo():
return 1

@exc_chain.exc_aware
def bar():
return 0

@exc_chiain.exc_aware
def foobar(x, y):
return x / y

x().y().z()
ret = exc_chain.get_return()

exc_chain.reset()

foobar(foobar(foo(), bar()), foo())
ret = exc_chain.get_return()

#

so long as you're willing to decorate all of the involved functions, it should work (though I haven't tested it that much)

dusk comet
#

there are no caching self._repr, so this code calculate repr every time
or am I missing something?

elder blade
#

Yes that looks to be it

#

What's the problem? You don't print a handle that often.

fallen slateBOT
#

Lib/asyncio/events.py line 71

self._repr = repr(self)```
dusk comet
#

we shouldnt cache repr before closing, because it may change

elder blade
#

I don't get why it should be cached (why is that such a big issue)?

fallen slateBOT
#

Lib/asyncio/events.py lines 67 to 71

if self._loop.get_debug():
    # Keep a representation in debug mode to keep callback and
    # parameters. For example, to log the warning
    # "Executing <Handle...> took 2.5 second"
    self._repr = repr(self)```
craggy jay
#

heyy a lil help pls

#

Write a python program to create a function which has operations to find cross product and dot product of two three dimentional vectors. Call the function in your program and use its functions.

craggy jay
#

oh okay thank you

heady mauve
#

If I pass a list object as a parameter to a class's __init__ and it is stored in the class instance, then does the list stored in the class instance update when I .append() the original list?

#

Or does it make an independent copy of the original list?

flat gazelle
#

the only way to copy a list is to call the .copy method, or construct a new list using some other way.

#

assigning a list never copies it

heady mauve
#

ok

pseudo cradle
#

!e

x = 0
try:
  x+=1
  raise
except:
  x+=1

print(x)

Has something like this ever been proposed where the state is saved before the try block and reverted to that state if an error occurs.

fallen slateBOT
#

@pseudo cradle :white_check_mark: Your eval job has completed with return code 0.

2
pseudo cradle
#

It's not immediately intuitive that the above code should produce 2 instead of 1

#

One could argue that the onus is on the developer to make sure something unexpected doesn't happen like that, though.

surreal sun
white nexus
#

^

#

just make a context manager to reset state

surreal sun
#

True, but while raise might be a bit obvious that it'll go into an except, something that relies on something else that's calculated during runtime (i.e. a variable not existing and raising NameError) might not be so obvious

#

so you'd just have weird behavior if sometimes you'd skip to the except block without evaluating the try block vs other times

quick snow
#

It's impossible anyways. You can't reset the entire state. What if you make a network request/create a file/... in the try block.

elder blade
dusk comet
#

saving states will be very slow and not consistent operation

white nexus
#

and the general consensus is to not put a lot of statements in your try, and only catch specific exceptions

quick snow
#

Just for fun: this does roll the state back, at least state within Python.

import os
import sys
import inspect
from contextlib import contextmanager

@contextmanager
def atomic():
    ppid = os.getpid()
    cpid = os.fork()
    if cpid:
        os.waitpid(cpid, 0)
        # we didn't get killed: error occured, skip body:
        sys.settrace(lambda *a, **k:None)
        frame = inspect.currentframe().f_back.f_back
        def raiser(*a): raise RuntimeError
        frame.f_trace = raiser
        try:
            yield
        except RuntimeError:
            return
    try:
        yield
    except Exception:
        # rollback: we exit
        os._exit(0)
    else:
        # all good: kill state-preserved parent
        os.kill(ppid, 9)

x = 23
with atomic():
    x += 1
    1/0

print(x)
elder blade
#

That's so cursed I love it

surreal sun
#

^

bronze steeple
#

Is it possible, even if it’s really ugly, to not execute code under a context manager when the file is imported? (Aside from obviously putting it in a func or under if main)

#

For example only execute the code under a context if you explicitly ask for it to be executed

flat gazelle
#

not really, the __enter__ can raise an Exception, but it has to be handled if you want to not crash. If you want things like bytecode manipulation, ask in #esoteric-python

#

if you want conditional execution, consider a decorated function, sth like

def main():
    ...
    @with_file('in.txt', really_execute=__name__=='__main__')
    def _(f):
        print(f.read())
    ...
bronze steeple
#

Thanks
I think bytecode manipulation will be best. Since I would have to catch any exception, to not crash, it’ll just be as if I never raised the exception.

quick snow
bronze steeple
#

That’s awesome! Let me take a look

#

@quick snow
On phone so bit hard to read… is your code executing the code under the context and then rolling back the state or does it have the ability to completely ignore whatever is under the context and come back to it at a later “date”?

quick snow
bronze steeple
#

Ok, Thanks. Excited to see this work

full jay
#

Is there any built in way to overload methods or functions? Mainly a curiosity than anything else

sonic flax
flat gazelle
#

there is functools.singledispatch

#

overload is afaik a typing thing

spice pecan
#

Yeah, typing.overload

#

It doesn't provide dispatching, only affects the typehints and IIRC even throws an exception if you attempt to run a decorated func

#

!e ```py
from typing import overload

@overload
def test(i: int):
print('int')

@overload
def test(i: str):
print('str')

test()

fallen slateBOT
#

@spice pecan :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 11, in <module>
003 |   File "/usr/local/lib/python3.10/typing.py", line 1986, in _overload_dummy
004 |     raise NotImplementedError(
005 | NotImplementedError: You should not call an overloaded function. A series of @overload-decorated functions outside a stub module should always be followed by an implementation that is not @overload-ed.
full jay
#

So that'd only really be used for structuring?

flat gazelle
#

ye, it's a thing for type hints

full jay
#

Ah okay. In the docs, "For the benefit of the type checker only"

#

Got it

flat gazelle
#

functools.singledispatch actually checks the type of the first argument using its annotation

full jay
#

Only the first?

flat gazelle
#

ye

#

there is a multiple dispatch decorator in a pypi package somewhere

#

but no builtin one to my knowledge

full jay
#

Yeah I've seen a couple

#

It was more a curiosity thing

halcyon trail
#

note that properly speaking overloading is a static type thing by definition, and is separate from multiple dispatch/multi-methods

full jay
#

Fair enough

glass olive
#

I’m moving on to learn java

#

Python is too easy

dark granite
quick snow
halcyon trail
#

do people really use asserts in python

#

I did at first but then it rapidly started to become pointless

jovial flame
#

In testing, yes

halcyon trail
#

that's a different thing

#

the asserts provided by test frameworks are not the same thing as the built in language assert

frigid trout
#

unittest pytest uses assert statements

pseudo cradle
#

Yeah, I use assert in testing

#

and literally nowhere else