#internals-and-peps

1 messages · Page 47 of 1

wide shuttle
#

Alright, how do we all feel about the "parenthesisless functions calls" that have just been proposed on Python Ideas by Guido van Rossum? While the proposal is an early prototype and some of the details are not exactly clear yet, the main idea is to offer an alternative way of calling functions with one argument.

When you want to do this:

len("abc")

you'd also be able to do:

len "abc"

For anything other than calling a function with one argument, you'd still need parentheses.

The change is made possible by the new PEG parser that allows for simple backtracking and it's obviously partially fuelled by nostalgia:

print "Hello, I belong in Python 2"

More info: https://mail.python.org/archives/list/python-ideas@python.org/thread/NCQX6ZIBREUTLS52VVG3DSZ43OEXJFTT/

gritty pebble
#

I dislike it, I don't see a real point in that coming back. I don't see how that would be beneficial

visual shadow
#

What is dead should stay dead.

#

There should be one, and only one, obvious way to do it.

gritty pebble
#

Imo it's more readable with parenthesis anyways

visual shadow
#

Poor Guido is probably gonna get the zen quoted at him so many times now all over again

languid dagger
#

That's not even behavior that other popular languages use. Can't say I'm a fan of it.

wide shuttle
#

Some partial examples of this behavior in other languages (okay, one other language) are mentioned in the email thread.

#

But, I can't say I'm a fan either

charred wagon
#

Pretty much agree with the zen quote

#

Inconsistencies in syntax just lead to confusion.

#

I don't think the parenthesis are unreadable to begin with, so removing them isn't much of a benefit.

#

In fact, I like the clear separation they provide between args and func name

wide shuttle
#

I think we do not need more language features that more or less "hide" what they do. After adding this, you'd have to learn that len "abc" is actually doing just len("abc") despite looking visually very different. It was okay back when print was a statement, because print was not just doing that; it was just the way print worked. There was no opaque, hidden magic of a parser that will silently call a function in a special, non-obvious way.

#

We already have some language features that obscure some essential parts of the language (like a def statement essentially "just" creating a function object and assigning a name to it; the syntax looks different, so people assume it is very different from, say, name = [1, 2, 3]).

#

Adding multiple ways to do the same thing that will create inconsistencies in styles and make obvious thinks less recognizable, less obvious, are not the right approach.

#

Despite me "growing up" with a print statement and having had nostalgia for a long time.

charred wagon
#

Well, I welcome it where it greatly improves readability, like with def.

grizzled vigil
#

Personally, I think the "one obvious way" quote from then zen is often overused to oblivion (to an extent that even Tim Peters wouldn't condone). In this case, I don't see a clear practical benefit from the feature, but I'm not strongly opposed to it either.

wide shuttle
#

Yes, I agree that def greatly improves readability, but I used it as an example of how "hiding" some of the details hinder learning about those details

#

I wouldn't change def itself

wispy jacinth
#

Reading the thread, it seems he talks about it to be able to dismiss it when people will tell him "lets bring back python 2 print" inevitably

grizzled vigil
#

I think it's also very much a case of "hey look, the new PEG parser can do this without issues" rather than a formal proposal (despite Guido saying that he's "seriously proposing" it)

wispy jacinth
#

Yeah

wide shuttle
#

Yeah, I got the impression that he had a lot of fun playing around with the parser. On the other hand, he must know that proposing this will trigger reactions.

wispy jacinth
#

I dont want to have meaningless code style argument at work about print statement so i dont like it 😂

raven ridge
#

Expert level trolling by Guido, I think.

ruby spruce
#

Only good thing I see on this () removing is migrating from old Python 2 (print) so no need to rewrite print statements

raven ridge
#

@ruby spruce but that's by far the least difficult part of a 2 to 3 migration, a part that automated tools can do perfectly

ruby spruce
#

Yeah

raven ridge
#

I could see that it might be useful for writing a DSL in Python, I guess...

wide shuttle
#

@quasi magnet Cut it out.

gritty pebble
#

I feel like if parenthesis are gonna be required for any function call that has multiple parameters or named parameters. It just makes more sense for them to be required everywhere, it should remain consistent across the board.

raven ridge
#

I like the suggestion to allow the syntax but with different semantics, from the Jupyter magics perspective. Having two ways to call a function feels unnecessary and difficult to teach, but imagine if we had a magic method that could take a string (the rest of the line it's used on, like a Jupyter magic) and return an AST or code object to substitute that line with?

#

Bonus: this approach could allow print foo to work (by substituting it with print(foo)), and would even allow print >>sys.stderr and print x, to work - print would just get a new magic method called __linemagic__ or something like that, and the parser would know that whenever it see a name followed immediately by another name or literal it should tokenize it as a call to the first word's __linemagic__ taking the rest of the line as a string argument.

#

It would essentially allow bringing macros to Python, with all the good and bad that comes with that 😄

true hollow
#

macros are really powerful

grizzled vigil
#

Also very easily abused, which is definitely a concern. Macros can be useful for quick shortcuts, but can get quickly convoluted when they become overly complex.

raven ridge
#

Consenting adults mumble mumble.

grizzled vigil
#

Yeah, but that only goes so far, vaguely similar to why python doesn't have a goto.

raven ridge
#

If we did this, it could! 😄

grizzled vigil
#

Perhaps then the better question is not if it could be done, but if it should be done ;)

true hollow
#

when i got into python i was into assembly

#

it was quite hard to me without the gotos lol

raven ridge
#

Well, I think Jupyter and IPython are proof that there's an appetite for macros in creating DSLs. In their case they wanted a repl that accepts a superset of Python as input, and the magics act as macros to glue the DSL together. So, it's not conservative, and it would be a huge change to the language, but macros like I'm proposing would probably get ignored by average developers most of the time, like metaclasses are, but would be available for when they're the best tool for a job (like creating a DSL on top of Python)

grizzled vigil
#

If you're serious about the proposal, I'd recommend writing up something formal and putting it on python-ideas@python.org to see what the others think.

#

I personally have zero experience in that area and don't know how viable the existing options are.

raven ridge
#

As another example, Cython is written in a superset of Python, but also makes much of that functionality available as Python methods and decorators to allow writing Cython code that's "backwards compatible" and can run in a regular Python interpreter. Macros would perhaps let the Cython cdef statements be run everywhere, removing the need for some of the Python replacements.

#

So far I think it's a good idea. One of the PEG parser authors is a coworker, I'm gonna suggest it to him tomorrow and see if he tells me it's stupid before putting it out on ideas 😄

true ridge
#

Where can I find info on what kind of code optimisations CPython does at compile or runtime?
@unkempt rock (extra to what @peak spoke said) most of the optimizations is now moved to ast optimizer which is located under Python/ast_opt.c

deft pagoda
#

i like no parens --- anything that requires less typing and less boilerplate

cloud crypt
#

Ah yeah, salt, I took your ast printer and refined it to PEP8 + added typings and removed walrus lemon_pleased

#

not really related to this channel

#

do you mean discord bot under "bot"?

lapis cove
#

it tells u when a given ast node starts and ends in teh source tree

worldly venture
#

ohhhhhhhhh

lapis cove
#

and lets u generate nicer err msgs 😄

civic dune
#

well its just one way the thing will communicate

worldly venture
#

oh that's awesome yeah

#

well that'll really come in handy

lapis cove
#

i wrote a programming langauge that looks like python for work

#

but isnt

#

but i was able to just hijack the AST module

worldly venture
#

interesting 🤨

#

ah yeah

cloud crypt
#

lol

lapis cove
#

to do the parser lol

stable grail
#

is that a accepted thing?

#

thats kinda great

lapis cove
#

but i can't get the end lineno to render nicer error messages

worldly venture
#

right

civic dune
#

is there a channel for "threading"?

worldly venture
#

well that's cool

cloud crypt
stable grail
#

i only use jupyter notebook with the ast module thing enabled when i inspect the tree.

civic dune
#

ah, thank you

worldly venture
#

I've been meaning to try write some sort of transpiler using AST for the funsies

#

I remember b1nzy teasing that compy thing on Twitter a while ago which looked cool

stable grail
#

he has so silly names.. and great names 😄

worldly venture
cloud crypt
#

eivl, remember when I told I was working on memory editing/reading with python?

lapis cove
#

ya the thing i wrote

#

is a way to represent a DAG in a python-like syntax.

#

for a rules evaluation engine

cloud crypt
#

i64

stable grail
#

yes i remember

worldly venture
#

ohh interesting

cloud crypt
#

alright so you know what is not fun? injecting 32-bit DLL into 32-bit process (which is fine) but from 64-bit python lemon_pleased

stable grail
#

sounds like a lot of micro-management

worldly venture
#

that does sound like a sweet use case for AST

stable grail
#

i think you should write a transpiler using ast joe, or anything really.

worldly venture
#

the last real AST project I saw was someone trying to implement elixir pipes with ast lol

stable grail
#

its really nice practice to work with the ast to get some knowledge about advance topics in python

worldly venture
#

pipe operator when 😔

lapis cove
#

the DAG syntax is also static typechecked 😮

#

we walk the AST multiple times like mypy does

stable grail
#

whats the pipe operator in elixir?

lapis cove
#

|>

stable grail
#

i mean, what does the operator do

lapis cove
#

foo |> bar is same as bar(foo())

stable grail
#

oh.. thats very possible to do with the ast

lapis cove
#

no thats not

#

idk what that is

worldly venture
lapis cove
#

u cant do that with python ast.

true ridge
#

yea, because python can't parse |>

worldly venture
#

yeah, with another symbol you can

cloud crypt
#

tokens time blobthink

worldly venture
#

lol

true ridge
#

lib2to3 time

lapis cove
#

repurpose the @ operator

stable grail
#

yes, i meant the syntax, not the parsing of the symbol 😄

worldly venture
#

@lapis cove what does DAG look like in a python syntax? sounds either pretty or scary

stable grail
#

but you could monkey patch the grammar could you not?

lapis cove
#

no its very tame

true ridge
#

but you could monkey patch the grammar could you not?
@stable grail In AST, no. But you can use the internal parser generator on the lib2to3 to patch the grammar and regenerate a new parser from it

lapis cove
#
A = Foo()
B = Bar()
C = Baz(A)
D = Qux(B)
cloud crypt
#

works like magic

true ridge
#

it would output a very raw CST, but its not too hard to work on that

lapis cove
#

is a basic DAG

stable grail
#

cool

worldly venture
#

right, that's pretty nice

#

I need to look more into DAG stuff

lapis cove
cloud crypt
#

this font makes my eyes feel weird

lapis cove
#

And we can execute it out of order

worldly venture
#

Ah right

cloud crypt
#

please monospace code font next time

lapis cove
#

Given this knowledge,

Foo = SomeUdfThatThrows()
Baz = SomeUdfThatDoesNotThrow()

can execute concurrently.

#

and ```
Bar = DependentFunction(input=Foo)

can start execution when 

Foo = SomeUdfThatThrows()


finishes, but does not need to wait for 

Baz = SomeUdfThatDoesNotThrow()

worldly venture
#

So you're changing execution order to figure out what can run concurrently? (trying to grasp this)

lapis cove
#

we traverse the dependency graph

#

well

#

the AST

#

to build a graph of each function and where it gets its inputs from

#

so we know what inputs can be concurrently calculated

#

and what order to execute the functions in

#

so in this "language" execution order is not guaranteed

worldly venture
#

oh that's awesome

lapis cove
#

the runtime will pick what order to execute functions in, and execute functions within the "script" concurrently to satisfy the requirements of dependent functions

cloud crypt
#

I think there is a good bunch of edge cases for that

lapis cove
#

not really

#

not if you scope your language down to a subset of python like we did 😛

#

which means when you are writing a rules language that is responsible for the extraction, transformation and classification of an event.

we just care that the result is deterministic, but not the order or sequence in which the script that runs the rule executes in.

grizzled vigil
#

how would you handle situations where guaranteed execution ordered is needed? or would that simply be outside of the scope of this "language"?

lapis cove
#

thats out of the scope of this language

#

execution order is defined by what depends on what

#

which is generally all you need.

#

if you want A to execute before B, you must have A be an input to B.

#
A = Foo()
B = Bar(A)
#

this will guarantee that Foo always executes before Bar, and that the result of Foo is visible.

grizzled vigil
#

Sure, but I could definitely imagine the dependency of inputs getting rather convoluted for non-trivial cases

lapis cove
#

ya

#

like what?

#

one thing we also do is we have a compilation phase to the script where functions can do their own custom validation of constant expressions within the AST

#

so we can surface these kinda errors at compile time:

error: invalid regex pattern
--> main.sml:1:25
     |
   1 | Foo = RegexMatch(pattern="(", target="")
     |                          ^ error: missing ), unterminated subpattern at position 0
worldly venture
#

that's pretty awesome

lapis cove
#
error: unknown identifier
--> main.sml:2:8
     |
   2 | Foo_A = UserNamw
     |         ^ this identifier not found
~~~ however, a similar identifier was found here:
--> (1) bar.sml:2:0
     |
   2 | UserName = "hi"
     | ^
#

anyways we'll be open sourcing all of this probably later this year 😛

worldly venture
#

ohhhhh excellent

grizzled vigil
#

I'm quite excited to see what this will look like in action, it seems rather interesting

worldly venture
#

the only thing I've had use for on discord github so far is instruments and semaphore, will be fun to play with something python this time lol

worldly venture
#

lol, release announcement for 3.9.0b3 ```
On behalf of the entire Python development community, and the currently serving Python release team in particular, I’m pleased to announce the release of Python 3.9.0b3. Get it here:

https://www.python.org/downloads/release/python-390b3/ https://www.python.org/downloads/release/python-390b3/
Wait, Beta 3? What happened to Beta 2?

Beta 2? Speak of him no more. We disappeared him. He was a bad release. Truly awful. I get shivers just thinking about it. Never mention that name again in this house.

I mean, long story short, in Beta 2 you couldn’t do urllib.request.urlopen("https://www.python.org").read() because it wouldn’t find root certificates due to a bug https://bugs.python.org/issue40924. Since this was a problem only apparent on an installed Python, it wasn’t identified by unit tests and was only found by Ned while he was testing his Mac installer. By the time we learned of the severity of the bug I already tagged and published the release on python.org http://python.org/. That’s why we couldn’t just re-do the release under the same version.

hollow crane
#

surprising that they don't test installer behaviour to some extent

#

or at least given that they recommend certifi installation in the installer

unkempt rock
#

how can I print all isntances of a class?

#

like is there faster ways then print(classname.var)

hollow crane
#

all properties of a class?

unkempt rock
#

Yes

hollow crane
#

print(dir(classname))

unkempt rock
#

oh ok thanks

hollow crane
#

that's not a good way though

unkempt rock
#

oh

hollow crane
#

you should remove the ones that start with __

undone hare
#

or at least given that they recommend certifi installation in the installer
@hollow crane certifi on the interpreter would be too slow to update, that'd be dangerous

narrow kettle
#

damn that dag python thing was cool

subtle pike
#

OOO execution would be cool to see but I can see some limitations where you encounter CAPI calls or IO

narrow kettle
#

im assuming it either doesnt do that or it waits on those to finish

#

which kinda invalidates the whole point cuz IO will take exponentially longer

subtle pike
#

I'd imagine they present hard execution barriers where the interpreter must wait for all prior results to compute before progressing

undone hare
#

You'd probably want some asynchronous IO here

narrow kettle
#

I'd imagine they present hard execution barriers where the interpreter must wait for all prior results to compute before progressing
i think thats what he was saying

#

its just so much slower u arent really saving much if ur result depends on IO

subtle pike
#

It's not just IO, it's any operation that leaves pure python (or marked pure CAPI functions)

#

if you can't guarantee that it's pure or isn't requiring the state of a previous operation, it can't be parallelized

narrow kettle
#

i mean it depends on the speed of the api call

#

im assuming the lang is a specific subset similar to a functional lang

#

every function has defined input

#

and defined output

#

and that state is immutable and internal

#

so you dont need to worry about anything other then what comes in and what goes out

#

so you can guarantee its pure becuase its a subset of python you defined

subtle pike
#

huh? Most functions in python don't have referential transparency, they're impure. A CAPI call cannot be reasoned because you no longer have the AST to chase, you can only mark those functions that are pure or that they mutate.

narrow kettle
#

yee most functions in regular python

subtle pike
#

However, I do wonder if it's a reasonable assumption to parrallellise a C extension that relinquishes the GIL (assuming you don't do anything impure with the OS)

narrow kettle
#

they wrote their own implementation

#

at least thats what i thought he said

#

this is a separate lang implementation

subtle pike
#

Yes, a separate language that is directly accessible from pure python

#

You can only reason about pure python or functions you've marked as pure or what they mutate

#

Otherwise, you cannot make any guarantees once you leave pure Python, no?

narrow kettle
#

hmmm the C functions could mututate state that other OOO operations depend on

#

that cant be validated ur right

unkempt rock
#

I forgot, how do you use randint to get a random integer in an alphabet?

undone hare
#

random.choice(string.letters) should work

unkempt rock
#

oops, i mean variable

subtle pike
#

you want to reference a random variable?

unkempt rock
#

I made a variable, and want it to choose a random integer in it

subtle pike
#

random.choice(locals())?

#

ah

#

what is the variable type?

unkempt rock
#

string

subtle pike
#

then use the code akarys, provided

unkempt rock
#

random.choice(string.letters)
AttributeError: 'builtin_function_or_method' object has no attribute 'choice

undone hare
#

Or random.choice(my_string)

#

You need the random module, not random.random

unkempt rock
#

i imported everything from random

undone hare
#

Basically, replace from random import random by import random

unkempt rock
#

from random import *

undone hare
#

Ah

#

Well, that's not a really good practice, but you should be bale to do choice(...) directly

unkempt rock
#

ok

#

thanks, it worked

full jay
#

Or if you only need the one

#

from random import choice

cloud crypt
#

@undone hare I always hate that almost everyone who works with ctypes and shows their code does from ctypes import * and then another star import from other library

#

just boggles my mind

undone hare
#

Yeah

full jay
#

Bad habits are hard to break

undone hare
#

My first project was star imports and globals lol

#

That was a mess haha

cloud crypt
#

I wrote a signleton a bit ago lemon_pensive

#
class Singleton:
    instance = None

    def __new__(cls, *args, **kwargs) -> Any:
        if cls.instance is None:
            cls.instance = super().__new__(cls, *args, **kwargs)
        return cls.instance```
#

Well it sounds better than globals you know

undone hare
#

That's cool

narrow kettle
#

i did that yesterday too lol

merry pollen
#

singletons blobsweatzoom

cloud crypt
#

Ah by the way I thought about working on a language that combines several languages I enjoy into one 😉

unkempt rock
#

I know I should use tuples to return several things, but how do I take out a variable from a tuple?

merry pollen
#

singletons are best done through metaclasses anyways

#

not that the distinction is... particularly significant in this case

cloud crypt
#

@merry pollen well it would be the class I sent with a bit of modifications, then class Singleton(metaclass=SingletonMeta) and that's it

#

@unkempt rock depending on your tuple and what you are planning to do

unkempt rock
#

I got 2 variables I want to return and got told before I should use a tuple, and I wanna use the variables inside a tuple for a check

cloud crypt
#
from typing import Tuple


def square_coords(x: int, y: int, z: int) -> Tuple[int, int, int]:
    return x ** 2, y ** 2, z ** 2


x, y, z = 1, 2, 3
x, y, z = square_coords(x, y, z)```
#

you either unpack it or access stuff by indexes

unkempt rock
#

Oh sorry i didnt realise i was in wrong 🤦‍♂️

merry pollen
#

@cloud crypt aye, i didn't look too closely at it on first glance

undone hare
#

You should never look closely to nekit's creations if you want to keep your mind

cloud crypt
#

I have set off on discovering most themes and fields I can work with in python

#

Low-level Web and AI/ML is left 👌

narrow kettle
#

How do you fire and forget an async method

#

I have an async messaging framework and i don’t need to await the messages that i send

wide shuttle
#

You could wrap it in a task with asyncio.create_task

narrow kettle
#

Ahh ok, does that throw it on a diff thread

wide shuttle
#

No, it wraps the coroutine in a task and schedules it in the event loop. It's just that you don't (have to) await the task right there and then if you don't want that.

narrow kettle
#

If i don’t await it will execution continue after the create_task call before that task is donee?

#

I’m assuming yes

wide shuttle
#

Yeah. create_task itself is synchronous, so you don't yield back control to the event loop when you use it

narrow kettle
#

Would the fact that the task i am creating is an async method change anything Here?

wide shuttle
#

No, a task always wraps around a coroutine object

narrow kettle
#

Perfect ty

worldly otter
#

When i use os.listdir(), it doesn't show me txt files for some reason. Anyone know how i can fix that?

wide shuttle
#

Hello, @worldly otter, if you want to ask a help question, please "claim" a help channel from the Python Help: Available category (see #❓|how-to-get-help). If you think that it's a quick question, #python-discussion should be fine, too. This channel is specifically meant to discuss Python itself, from a higher-level perspective and not for help questions. For more information, see the topic of this channel:

worldly otter
#

I'm sorry, and thankyou.

uncut sage
#

If I have a class with @property on one of the methods, is it possible to modify what that points to after creating a class instance?

#

setattr is rejected, so I'm wondering if there's another way to do it.

radiant fulcrum
#

I think ive managed todo it before

#

but it wasnt exactly pretty or non pycharm screaming at you

uncut sage
#

I think what I might need to do is have it point to a proxy function first, and then just alter the underlying proxy

radiant fulcrum
#

i think i ended up having it return diffrent functions

#

which pycharm didnt like

boreal umbra
#

Guido has said that he wants to make parentheses for function calls optional for 3.10

#

So len 'abc' would be valid

peak spoke
#

I don't think that will go through even on the proposed print

boreal umbra
#

Obviously the use cases are limited because you'd have to do funky stuff to parse nested calls

#

If we were to get a new function feature with limited use cases, I'd rather see @ for composition

#

(range @ len)('abc')

#

Bad example because range len is pretty much always wrong.

radiant fulcrum
#

I dont necessarily see the point in making the parentheses optional tbh

paper echo
#

ahhhhhhhh no

#

actually ok

#

@ for functions would be sweet

#

but yeah no i don't like no-parens

#

i don't like it in perl and i don't like it in ruby

#

python doesn't need even more ways to express the same thing

#

one of the great aspects of python is its uniformity of syntax

#

even having two kinds of equivalent quotation marks is messy enough

#

paren-less makes sense in haskell

boreal umbra
#

@ composition is limited because each function in the stack has to return something that the next function can use

paper echo
#

eh

#

if the function returns None and your next function errors on None that's your fault

#

mypy would have to be aware of @ though

#

and that could get messy

boreal umbra
#

I imagine it getting very messy if there's more than one argument for each function, too

#

Making sure that some functions return tuples, etc.

paper echo
#

presumably you just get typeerror with too many arguments

peak spoke
#

Different quotes improve readability considerably but the main idea was to bring a print "statement" back because the new parser allows the syntax

#

But I don't see any need for that

paper echo
#

agreed

peak spoke
#

Keeping function calls as they are keeps out a few lines in the python parser and imo are easier to parse by humans

radiant fulcrum
#

I think it makes it alot more readable aswell

paper echo
#

seems like a feature added just because the parser is more powerful so it's technically possible

red solar
#

wait are they bringing print back?

deft pagoda
#

look at all these people that like shift+9 unreachable keys, when guido offers a few less keystrokes

red solar
#

yeah but when you're used to languages where '' is a char, doesn't really matter that "" requires shift

deft pagoda
#

" is easy to type regardless

#

) is a pain

red solar
#

oh

#

sorta?

#

not really, i mean we're fairly used to that key just from function calls

boreal umbra
#

Hmm, are there mechanical keyboards that are made to make python easier?

red solar
#

just have your ide have a thing for print 🤷

#

pr and then tab to auto complete to print() with your cursor between the ()

hollow crane
#

where are you holding your fingers where () is hard to reach

#

or are US keyboards different

boreal umbra
#

It'd shift 9

#

It's *

balmy shadow
#

I got a issue 💀

#

I setted up a shitty HWId system thingy

boreal umbra
#

@balmy shadow take a look at #how-to-get-help

balmy shadow
#

For you? Sure!

boreal umbra
#

Anyway I don't like shift 9 because it pulls my hand all the way away from the home keys.

#

I guess I could do shift with my left and and 9 with my right

#

But I'm so used to only using right shift.

hollow crane
#

my defalut position is

#

hang on

#

left hand: little finger on shift, thumb on space, other fingers on WASD

#

right hand: little finger on enter but i press it with 3rd finger, 3rd finger on backspace and my 2nd finger is on the 0 key at all times

#

so i only have to depress my 2nd finger to type a )

void sonnet
#

look at all these people that like shift+9 unreachable keys, when guido offers a few less keystrokes
@deft pagoda outside of the "less shift", i think some of the responses are actually quite cogent on reasons not to do it. some are easily workable, but i think the foo(bar) or foo bar confusion is best avoided. especially after the long road to getting away from the print statement.

hollow crane
#

oh i just read your message about using right shift @boreal umbra

paper echo
#

code is read more often than it is written

boreal umbra
#

It's alright. I'm at work, which is not a computer job, so I'm barely online.

paper echo
#

imagine the chaos this would result in for new programmers

#

and its irreversible

#

once this is in python you can't take it out

#

imagine the flood of questions from people who start with a tutorial that doesn't introduce parens

#

a language like python really has to consider the new-user experience as much as the advanced-developer experience

#

and as an advanced developer i think this will turn the python community into a big fractured mess of people who prefer one style over the other

#

i truly do not see any benefit to that change other than chasing a fun whimsy

boreal umbra
#

Yeah, it seems like a proof of concept thing

rich wharf
#

what if we added a few things
attribute unpacking

#
class x:
  a = 1
  b = 2

{a, b} = x
#a is now 1, b is now 2
#

and unpacking defaults

#
(a, b, c = 1) = [1, 2]
#a is 1, b is 2, c is 1
#

and unpacking annotations

#
(a: int, b: int, c: int = 1) = [1, 2]
brave badger
#

Achieving attribute unpacking would be trivial by implementing __iter__ wouldn't it?

unkempt rock
#

Not a fan of defaults or attribute unpacking, but annotations might be sensible.

rich wharf
#

@brave badger nope

#

the attributes you reference with {a, b} are the names of the attribute you unpack

#

{a, b} = x is equal to a = x.a; b = x.b

brave badger
#

I see

#

Though it kinda seems like syntactic sugar for something like attrgetter, in my opinion anyways

from dataclasses import dataclass
from operator import attrgetter

@dataclass
class Point:
    x: int
    y: int

p = Point(5, 5)
x, y = attrgetter("x", "y")(p)
rich wharf
#

@brave badger that attrgetter code looks horrendous

#

{x, y} = p is so much more readable

brave badger
#

Alternatively, why not just reference the attributes themselves?

north root
#

yeah, i don't particularly see any point of having that

rich wharf
#

I think it would be convenient

grave jolt
#
import inspect

def destructure(obj):
    if not isinstance(obj, dict):
        raise TypeError(f"{obj} is not a dict")
    parent_frame = inspect.currentframe().f_back
    line = inspect.getframeinfo(parent_frame).code_context[0]
    var_names = map(str.strip, line.split("=")[0].split(","))
    for var_name in var_names:
        yield obj[var_name]

my_dictionary = {"a": 42, "varr": 666, "_": ()}
_, a, varr = destructure(my_dictionary)
print(a) # 42
print(varr) # 666
print(_) # ()
#

Although it doesn't handle all multiline cases

brave badger
#

That's quite interesting

deft pagoda
#

i mean, just define an __iter__ for your class and then you can unpack it

unkempt rock
#

hurt bran

deft pagoda
#

you could just try:

In [1]: my_dict = {'a': 123, 'var': True, 'something_else': 1234}                                                  

In [2]: globals().update(my_dict)                                                                                  

In [3]: a                                                                                                          
Out[3]: 123

In [4]: var                                                                                                        
Out[4]: True

In [5]: something_else                                                                                             
Out[5]: 1234
#

or you can use astuple if you're using dataclasses:

In [6]: from dataclasses import dataclass, astuple                                                                 

In [7]: @dataclass 
   ...: class Point: 
   ...:     x: int 
   ...:     y: int 
   ...:                                                                                                            

In [8]: x, y = astuple(Point(1, 2))                                                                                

In [9]: x                                                                                                          
Out[9]: 1

In [10]: y                                                                                                         
Out[10]: 2

stable grail
#

oh nice.. i think i have missed astuple

#

!d dataclasses.astuple

fallen slateBOT
#
dataclasses.astuple(instance, *, tuple_factory=tuple)```
Converts the dataclass `instance` to a tuple (by using the factory function `tuple_factory`). Each dataclass is converted to a tuple of its field values. dataclasses, dicts, lists, and tuples are recursed into.

Continuing from the previous example:

```py
assert astuple(p) == (10, 20)
assert astuple(c) == ([(0, 0), (10, 4)],)
```  Raises [`TypeError`](exceptions.html#TypeError "TypeError") if `instance` is not a dataclass instance.
grave jolt
#

ah, the great underscore shortage

#

it's like vowel shortage in C

#

My favourite are wcsrtombs and wcsxfrm

tacit hawk
#

how can I avoid loops when overriding __getattribute__?

#

The superclass is object, I tried to call the parent implementation but it did not work. Should I lookup directly in __dict__?

unkempt rock
#

is there a thingy in python that is going to eval variable/function by walking prototype up in python

#

in ruby there is self.send(someVar)

spice pecan
#

If you need to get an attribute by its string name, you can do some_obj.__getattribute__('attrname')

unkempt rock
#

!d assert

fallen slateBOT
#

This appears to be a generic page not tied to a specific symbol.

spice pecan
#

Though a more readable solution would be to use getattr or operator.attrgetter

wide shuttle
#

@unkempt rock We have a #bot-commands channel for commands like that

#

This channel is strictly for on topic conversation

unkempt rock
#

Oh thx :) @wide shuttle

boreal umbra
#

Are there languages that use a question mark as an operator?

void sonnet
#

ternary?

boreal umbra
#

Ternary?

spice pecan
#

condition ? val_if_true : val_if_false

#

this thing

boreal umbra
#

Ah

void sonnet
#

yeah... (haven't C'd in a while, wanted to verify. hehe)

spice pecan
#

It's also used for null-coalescence in C#, for example

#

a ?? b is equivalent to a != null ? a : b

boreal umbra
#

So use a if it's not null, else b

spice pecan
#

yeah

#

and you can chain it

#

a ?? b ?? c and so on

boreal umbra
#

I do something similar with the or operator a lot.

spice pecan
#

There was a pep for a similar thing in python, which would check specifically for None rather than truthiness

boreal umbra
#

How'd that go?

spice pecan
#

It was deferred I believe

boreal umbra
#

Hmm

spice pecan
#

So not completely out of question, but not yet

tacit hawk
#

I am trying to lazily compute an attribute, maybe I should use data descriptors

wide shuttle
#

You could do that. One way to do that is by using the built-in property descriptor

ruby spruce
#

How PEP numbering works? I don't understand it.

wide shuttle
#

Unless you want to have slightly different behavior (like having a non-data descriptor that will be invoked only the first time and then sets a value in the object's __dict__ to ensure the value is fetched directly the second time)

peak spoke
#

I don't think the numbers are special above 100 or something it was

mellow moth
#

can anybody help with python websockets? il buy pizza ! okhandbutflipped ( im desperate 😩 )

peak spoke
#

maybe rememberable numbers for important peps, but you can check pep 1

spice pecan
#

You could just use a hidden attribute that is set to None by default

@property
def value(self):
    if self._value is None:
        self._value = do_calculation()
    return self._value
hollow crane
#

if you've asked in a help channel and no one's responded etc for a while then i apologise

wide shuttle
#

@spice pecan Yes, although that will call the underlying method each time, which is usually not that important

undone hare
#

Can you put LRU cache on a property? blobthinkingdown

grave jolt
#

@boreal umbra JS also has ?-operators, but I believe they're only available on Chrome now.
a ?? b = a === null ? b : a
a ?. b = a === null ? null : a.b

wide shuttle
#

@undone hare you could also do something like this:

#

!e

class LazyAttribute:
    def __init__(self, function_object):
        self._function_object = function_object

    def __get__(self, obj, owner):
        if obj is None:
            return self

        bound_method = self._function_object.__get__(obj, owner)
        result = bound_method()
        setattr(obj, self._name, result)
        return result

    def __set_name__(self, owner, name):
        self._name = name


class Foo:

    @LazyAttribute
    def attribute(self):
        print("Calling the method")

        # heavy calculations
        return 100


f = Foo()
print(f.attribute)
print(f.attribute)
fallen slateBOT
#

@wide shuttle :white_check_mark: Your eval job has completed with return code 0.

001 | Calling the method
002 | 100
003 | 100
wide shuttle
#

This is a non-data descriptor, so setting the attribute on the actual instance will eclipse the method/descriptor

#

And that means it will only run the first time when the attribute does not exist yet

#

After that, it's accessed like a normal attribute

grave jolt
#

I think there was a suggestion to make a single-fire LRU cache decorator on the mailing list, but it was dismissed

#

so in Haskell you can even 'emulate' JS's ?? and ?.

(??) :: Maybe a -> Maybe a -> Maybe a
(??) Nothing y = y
(??) x _       = x

(?.) :: Maybe (t -> a) -> t -> Maybe a
(?.) Nothing _ = Nothing
(?.) f       x = Just (f x)
tacit hawk
#

Yes I wanted that, compute one time and override the proxy attribute

undone hare
#

That's smart ves

tacit hawk
#

I think that is common when implementing lazy loading

#

data descriptors helps a lot

undone hare
#

There's a PEP about null safe operations, did anyone already sent the link?

grave jolt
undone hare
#

I'm at the same time "that's an enormous game changer" and "that ain't feel like python" on this PEP

tacit hawk
#

it is optional

spice pecan
#

I'm not sure about?. and ?[], but ?? would definitely be nicer than val if val is not None else default

tacit hawk
#

for reading of course the last is best

spice pecan
#

We already have similar behavior on or, but a version that specifically checks for None would be really convenient

tacit hawk
#

The value of an instance is what is returned by __new__?

peak spoke
#

new creates the instance

tacit hawk
#

Ok I found in the docs, it is "... The return value of new() should be the new object instance (usually an instance of cls)."

grave jolt
#

or can be a subtle defect.

#

When one argument is mutable.

#

Like a cache or something.

magic python
#

anyone know why mpl would use complex numbers for a grid of plots?

hollow crane
#

Complex numbers are often used as a coordinated system

#

If you knew that and it doesn't help then sorry I don't know

#

Coordinate system

red solar
#

And the best part is that with complex numbers, abs() will give u the distance from 0,0 to the coordinate 🙂

#

Uhh

hollow crane
#

purge

red solar
#

For stuff like asyncio, can u implement that just by wrapping non blocking io in a coroutine?

shadow hinge
#

Suppose I have multiple instances of selenium Chrome webdriver, each instance is started programmatically with different settings. I wish to recognise each session and close that specific instance from all available instances when user hit close, programmatically... I've read about session IDs in selenium but not sure how to use it to close sessions. Couldn't find anything in documentation either so here for help.

north root
shadow hinge
#

I tried posting there several times.. no help :(

red solar
#

As in you want to end all sessions that you started?

hollow crane
#

why not have a list of sessions

#

is there any reason you can't just have a variable for the session to reference it rather than using ids

north root
#

yeah, you may have to post many times before getting an answer. we're all volunteers here after all 🙂

shadow hinge
#

No a specific session form all available sessions

red solar
#

I’m still convinced the non floating help channels was better

coral pebble
#

Usually you have a list of sessions with an event trigger that operates on a given session to close it I think

shadow hinge
#

So how should I solve this?

grave jolt
#

Please ask in a help channel. This is not a help channel.

#

PyDis channels are strongly typed. You caused a TypeError: expected HelpChannel, got GeneralDiscussionChannel

red solar
#

Lmao

radiant garden
#

PyDis channels are strongly typed. You caused a TypeError: expected HelpChannel, got GeneralDiscussionChannel
Actually passing a message into a raise rather than just tossing in the value that caused the error? That's impressive.

subtle pike
radiant fulcrum
#

Gunicorn with gevent Flask 12 24 136 3077 12 workers oof

undone hare
#

Well, sure async isn't faster, that's not the goal of asynchronous programmation, the point is to have a more responsive software

radiant fulcrum
#

I find it interesting that they took the Sync libs upto 16 Workers but failed todo that with some of the higher async libs like sanic and aiohttp

undone hare
#

Well you could have many asynchronous worker, but there isn't so much point in it, since the bottleneck will still be the computations behind the scene

vast escarp
#

I’m still convinced the non floating help channels was better
@red solar having been a helpful member in a lot of other discords for different topics, the floating help chat is a dream

#

It might be a bit slower to get help but not having 15 people talk over and around you is pretty great

red solar
#

fair enough

flat gazelle
#
PS C:\Users\adamh> type test.py
u = int(input('how old are you')
if u <= 18:
    print('underage')
else:
    print('adult')
PS C:\Users\adamh> py test.py
  File "C:\Users\adamh\test.py", line 2
    if u <= 18:
              ^
SyntaxError: invalid syntax
```is there any reason why the error is so unhelpful. This seems like quite the common mistake and a more descriptive error would probably be quite useful.
red solar
#

you're missing a bracket

#

at the end of u = ...

hazy anchor
#

i actually am surprised thats the error its throwing too.

flat gazelle
#

I know, the error should show that though

peak spoke
#

With the line continuation the syntax is invalid at the point the statement comes in

red solar
#

you get used to it, python tends to put a lot of syntax errors on the next line

hazy anchor
#

why would the parser be accepting the if u <=.. before it i wonder.

peak spoke
#

It'd need to serach for a newline or something to provide a meaningful error

flat gazelle
#

because ```py
(int(input()) if u <= 5 else 10)

hazy anchor
#

ah, the bloody ternary form.

#

gotcha.

undone hare
#

The parser will accept all the characters until it find the :, which isn't what it would except

#

You should take a look at the Grammar folder in the CPython source code

flat gazelle
#

It seems like the error could be improved though

undone hare
#

It is kinda hard tbh, because of the way the parser work

peak spoke
#

in caes like

u = int(input('how old are you') if u <= 18: print('underage')

I think the error is useful if the whole line is included but with improving it it becomes "what all to include in the error"

#

if I missed a closing token somewhere 20 lines above and with some specific circumstances it's all valid, does it spit out a huge error message?

undone hare
#

The CPython parser is the exact implementation outlined in the dragon book if you are curious, but basically the whole parser is a state machine

flat gazelle
#

flake8 places the error at the start of the expression, which I find quite reasonable. But it does match parens before parsing the expression

undone hare
#

It isn't the same parser, that's the issue

#

Having a comprehensive error out if a state machine is tricky because you don't know which info to actually provide, you just have a chain of previous states

flat gazelle
#

makes sense, I guess the true solution is to stop using bad editors

undone hare
#

Yup haha

true ridge
#

It would be helpful to use -d flag to understand how parser is behaving. For this case after the u <= 18 it was expecting an else (since it assumes this is an if expression) but when it got : it couldn't find a match and aborted.

#
 $ python -X oldparser -d t.py
Token NAME/'u' ... It's a token we know
 DFA 'file_input', state 0: Push 'stmt'
 DFA 'stmt', state 0: Push 'simple_stmt'
 DFA 'simple_stmt', state 0: Push 'small_stmt'
 DFA 'small_stmt', state 0: Push 'expr_stmt'
 DFA 'expr_stmt', state 0: Push 'testlist_star_expr'
 DFA 'testlist_star_expr', state 0: Push 'test'
 DFA 'test', state 0: Push 'or_test'
 DFA 'or_test', state 0: Push 'and_test'
 DFA 'and_test', state 0: Push 'not_test'
 DFA 'not_test', state 0: Push 'comparison'
 DFA 'comparison', state 0: Push 'expr'
#

an example of the output

unkempt rock
#

very cool

radiant fulcrum
#

The only issue that might come of that is that things like docker use -d to detach systems

#

which could get confusing

unkempt rock
#

a lot of tools use -d for debug mode

#

alternatively -v with different amounts of v for different verbosity levels

true ridge
#

yea, it means debug. But if it is confusing, you may just use it with setting PYTHONDEBUG env var

#

which is a bit more explicit

radiant fulcrum
#

yeah ig

#

somthing like -debug would also work tbh

unkempt rock
#

i imagine -d is analogous to --debug

radiant fulcrum
#

yh

unkempt rock
#

ah, there is no --debug

#

interesting

glass robin
#

Debug is true by default

#

Refering to the _debug_ variable

#

You need to use the -O flag in order to set it to false

#

Afaik not widly used

#

~~
In fact it does more than setting it false, it removes all assertions only depending of _debug_ being set to true~~

hollow crane
#

debugn't

glass robin
#

Hmmm, this is confusing for me:

-O
Remove assert statements and any code conditional on the value of __debug__. Augment the filename for compiled (bytecode) files by adding .opt-1 before the .pyc extension (see PEP 488). See also PYTHONOPTIMIZE.
What's remove in this context?

#

I though it meant it was not evalued somehow, but after some tests, If I've a syntax error in a __debug__ it still shows the error even with the -o flag

peak spoke
#
C:\Users\Numerlor>python -O -c "import dis; dis.dis('assert False')"
  1           0 LOAD_CONST               0 (None)
              2 RETURN_VALUE

C:\Users\Numerlor>python -c "import dis; dis.dis('assert False')"
  1           0 LOAD_CONST               0 (False)
              2 POP_JUMP_IF_TRUE         8
              4 LOAD_GLOBAL              0 (AssertionError)
              6 RAISE_VARARGS            1
        >>    8 LOAD_CONST               1 (None)
             10 RETURN_VALUE
#

It has to parse the code, but with the debug flag it's unreachable and can be removed

fresh spindle
#

how to use real time scrapped data to build an application or website which uses that data in real time

#

????

wide shuttle
#

Hey @fresh spindle, this is not a help channel, but rather a discussion channel to discuss Python itself

warm pebble
#

Is ok when reversed(my_str) sending me address of memory ?

flat gazelle
#

reversed returns a generator, if you want a reversed string, you can do

''.join(reversed(string)
# or
string[::-1]
``` you can still use e.g. a for loop to iterate over it
warm pebble
#

im just doing ctf and i fount that interesting

#

so when i compare
string and that reversed it will be true if that will be same ?

#

its like

my_str = str(numB)
rev_str = reversed(my_str)
if list(my_str) == list(rev_str):
  return True
else:
  return False
cloud crypt
#

palindrome strings

glass robin
#

There is a more efficient way to deal with it

cloud crypt
#
from typing import Any


def is_palindrome_str(some: Any) -> bool:
    some = str(some)
    return some == some[::-1]```
#

or something

glass robin
#

I think it is more efficient to do like that

n = len(my_string)
my_string[:n//2] == my_string[n//2+1::-1]
#

Ops, wrong channel, thought it was py-general

cloud crypt
#

==

glass robin
#

ofc

cloud crypt
#

but yeah it is more efficient

glass robin
cloud crypt
#
$ python2
>>> 3 / 2
1``` good times haha
near coral
#

I like the palindrome one

harsh dome
#

RIP the guy who was trying to install SDL

#

If he sees this: you can use SDL2 instead of SDL but then I think you have to build pygame yourself to configure it to use SDL2

#

at least that's what I had to do

frigid jackal
#

Heya, can i ask how weakref works? And then how I'd make my own import function that uses weakref

grave jolt
#

AFAIK, weakref is like a normal reference, but it doesn't add to the refcount of an object.

#

Every object in python has a reference count -- it's a number that shows how many variables (or other pointer) point to it

#

So here

x = []
y = x
z = (x, y)
u = [x] * 38

the list stored in x will have 42 references

#

If the refcount goes to 0, the object gets deallocated (not necessarily immediately, but likely soon)

#

But if you take a weak reference of x, you will not increase that counter, although you will still be able to get a normal (strong) reference out of it, which will increase the refcount

shut anchor
#

So it's the sort of thing you want to use immediately after you create it?

grave jolt
#

I don't actually know where weakrefs are useful, maybe in some sort of cache

shut anchor
#

I've seen them around in kivy.

frigid jackal
#

Oh okay

grave jolt
frigid jackal
#

Thanks!

grave jolt
#

It's like weak_ptr in C++

#

While normal variables are more like shared_ptr (but with actual garbage collection, so cycles will not cause leaks)

frigid jackal
#

Cool

#

I wonder if i could make a python module in Nim using python weakref :P

brave badger
#

TIL quite an interesting use case between weak references and generators.

from weakref import ref

class Point:
    pass

def life_time():
    p = Point()

    yield ref(p)

    for i in range(10):
        yield i

g = life_time()
p_ref = next(g)

for count in g:
    print(count, p_ref)

print(p_ref)
#

I can see how this would be useful for async stuff

narrow kettle
#

I don't actually know where weakrefs are useful, maybe in some sort of cache
i use them for my messaging module

#

i want events to be weak so they dont linger

raven ridge
#

I use them for ensuring background threads are stopped before modules are destroyed during interpreter teardown. I've got a library that exposes classes that must be explicitly stopped with a .stop() or __exit__. Things would deadlock if they aren't stopped, because the interpreter waits for threads to stop before beginning to tear down modules, but the only thing that stops them is a call to .stop() or __exit__. So I've got an atexit handler that calls stop if the user failed to call it, and it uses a weakref rather than a strong reference so that if the user does do the right thing those instances can be collected before interpreter teardown.

#

As one example, @grave jolt

boreal umbra
#

What is a weak ref?

charred wagon
#

Its a way to get a reference to an object which wont keep the object living

#

Py basically garbage collects when it sees an object has no more references

#

So a weakref wont count as a reference which prevents gc

crystal pebble
#

So... Would trying to use that reference result in a null pointer situation?

raven ridge
#

You "use the reference" by calling it, at which point it either returns a strong (regular) reference, if the object is still alive, or None, if it's not.

crystal pebble
#

Oh, okay

north root
#

this isn't a help channel

rich wharf
#

Minor change to my iter library

#

The apply function has changed, it now receives a callback which takes in the item, and an optional reject argument

#
iter(range(5)).apply(lambda i: i + 2).list() #[2, 3, 4, 5, 6]
#
iter(range(10)).apply(lambda i, reject: i + 2 if i > 6 else reject).list() #[9, 10, 11]
#

these are equal

#
.filter(lambda i: i > 6).map(lambda i: i + 2)
.apply(lambda i, reject: i + 2 if i > 6 else reject)
#

gonna add flatmap

undone hare
#

I wonder if Python uses static code analysis to remove redundant ref counts, but I'm not sure because of the mutability of the code

thin dawn
#

how do I calculate space complexity?

forest flume
#

print("hi")

limpid kelp
#

invalid literal for int() with base 10: '110.0' i know the problem but how do i fix it

lost nexus
#

110.0 is a float

#

not an integer

limpid kelp
#

how could i change it from a float to a int

unkempt rock
#

Is this a literal?

hazy anchor
#

convert it to a float, then from a float to an int.

#

int(float("10.0"))
10

lost nexus
#

what would be some usage cases of adding a weak ref to an object

limpid kelp
#

iv fixed it now

lost nexus
#

i don't really quite understand the use of a weak ref atm

hazy anchor
#

i think circular structures should use a weak ref.

#

but in python i dont recall ever actually making one.

lost nexus
#

in the weakref docs

A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it.
I don't get this. what is the point of a weak ref if it won't prevent the object from being garbage collected.

However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it.
Also, how long does it take for the GC to destroy these objects? It seems here that there's some grace period where the weak ref can still return the object just before garbage collection

peak spoke
#

The point of the weakref is that it won't prevent the GC from collecting the object

lost nexus
#

I think that clicked a bit, but I'm not sure. If you want an object to be GC'ed then just remove the strong references, why add a weak ref? I suppose this serves use in large cache implementations.

#
  • what is that grace period? if I'm understanding this correctly.
peak spoke
#

For example like paul creenis said you can use it with circular references so the object can actually be destroyed, in some cases it's not feasible to remove all the references through your data but you want it to be removed

lost nexus
#

let's say I have an object with some strong references on it, what happens if I add a weak ref?

peak spoke
#

you get an additional reference you can use, and if all the normal references are removed it'll allow the object to be garbage collected

#

when the GC happens is not really something you know about in your program unless you call it yourself

lost nexus
#

well, how long does it take for the GC to collect an object with only weak refs?

peak spoke
#

It'll collect them when it runs, there's no set time

lost nexus
#

doesn't that just instantly delete the object? It seems the weakref would always return None

peak spoke
#

Yes, in most cases it'll probably be collected before the next line can be executed (at least in synchronous code) and the weakref will return None

lost nexus
#

I'm struggling to see how a weakref would be used if its referent is just poofed instantly

hazy anchor
#

you can have two references to an object

#

one weak one strong

peak spoke
#

You wouldn't use it if you just dereference everything right away

lost nexus
#

@hazy anchor then that defeats the purpose of a weakref

hazy anchor
#

so it stops for instance the inner objects from keeping themselves alive, but lets the outer object control things as per normal

peak spoke
#

You keep a weakref around in a list or something, and then a normal reference where you work with that data

#

When the normal reference goes away, the weakref in the list allows the expensive object to be collected

languid dagger
#

Think of this scenario. You have a library that requires image data to be given and your library needs to store that to use. If you use a strong reference then that data will be alive for the duration of your program. If you use a weak reference then that will be cleared when the user's strong reference has been gc'd.

lost nexus
#

I don't understand in that scenario why we'd need a weak reference when we want the object to get collected when the strong reference is GC'ed, since you wouldn't need a weak ref to achieve this functionality.

peak spoke
#

If you used a normal reference in the place of the weakref you'd have to also dereference it there

languid dagger
#

Otherwise your library would be keeping that data alive in memory instead of allowing it to be gc'd when the user was done with it

peak spoke
#

With Wattle's example, the user would need to call an another thing that would have the purpose of deleting all the references to the image internally

lost nexus
#

so if there's a weakref & and a strong ref, we don't need to call on another thing with the purpose of deleting all the refs?

languid dagger
#

So long as the strong ref is cleared then yes. But if you have two strong refs and the user only has access to one of them then the data will not clear because the second ref is keeping it alive. So the user would have to possibly call some deallocate method or have the object holding the data get gc'd which may not always be possible

lost nexus
#

it sounds like weakrefs are something libraries should implement for their users since users usually only touch front end, am I on line here?

languid dagger
#

I believe that's the general use case, there are possibly other scenarios where you'd want to use them in your own code

lost nexus
#

I see.

hazy anchor
#

at the end of the day its little more than a reference which doesnt increment the refcount no?

#

no mysticism

narrow kettle
#

Weak refs are important in event systems

#

You don’t want an event subscription keeping an object alive when it otherwise would have died

deft pagoda
#

properties might have instance dicts, that would use weak refs

peak spoke
#

weakrefs are very important to have in python, but you won't really use them much yourself directly in simpler progrms

boreal umbra
#

Someone on python ideas proposed that a version four of python not be released until there's been up to 3.14 or something like that

#

Was 3.10 going to be the last 3 version?

deft pagoda
#

no

boreal umbra
#

Then what is this person talking about?

deft pagoda
#

dunno

#

i've heard no plans for a version 4

#

far as i know it'll go up to 3.9999999

peak spoke
#

4 was supposed to come after 3.9 for a bit but now the new yearly release cycle is approved with no plans for python 4 afaik

#

It may still be mentioned in the docs or some peps but the more imporant peps like 563 have all moved to 3.10 in their text. With that the last version would be 3.9

spark magnet
#

@boreal umbra 1) they might be joking, 2) they might be confused

boreal umbra
#

The first response is clearly a joke.

spark magnet
#

@boreal umbra i don't think Jonathan Fine's response is a joke, it's meant as a real thing that could be done, as a bit of wit.

crystal pebble
#

How much do you people worry about memory alignment in Python?

#

When you're writing general Python code, I mean... Not when you're developing Python itself

peak spoke
#

Never cared about anything memory related beyond usage

crystal pebble
#

Also, I hate trying to talk while or shortly after writing code. It becomes difficult to get back into a human mindset thanks to ambiguity in human languages

boreal umbra
#

@crystal pebble just do that with verbs as functions

#

If it's an active verb it can be a method. For passive verbs they can be stand alone

#

Prepositional phrases can be key word arguments

crystal pebble
#

lol, it's more that I start to think of edge cases too much. Since a lot of Python is written in Python it was bothersome

#

It becomes easier and less annoying after taking a break though, thankfully

unkempt rock
#

Same

uncut sage
#

@crystal pebble memory alignment as in cache alignment?

crystal pebble
#

I think so? Maybe

#

Like putting struct stuff in an efficient order in C

uncut sage
#

@crystal pebble In Python I have only ever worried about such things when, say, writing a C module in Cython

wide shuttle
#

Because they were not on-topic for this channel

#

This is a discussion channel only meant to discuss Python itself from a higher-level perspective

frozen finch
#

what other algorithms exist other than cycle detection for O(n) complexity for matching words from 2 different lists. For example:

list2 = [boy, toy, coy, rat, koi]```

I can use a double for-loop here like this:
```for x in list1:
    for y in list2:
        if list1[x] == list2[y]:
            repeated = list2[y]

but this implementation gives me O(n^2) complexity

radiant fulcrum
#

map() would probably a faster alternative or filter()

flat gazelle
#

sets maybe

peak spoke
#

Yeah can just turn one of them into a set and do intersection

frozen finch
#

reason for this is that im doing this with a 2 1000 entry lists

flat gazelle
#

yeah, sets are the way here

frozen finch
#

how would you use sets for this

#

oh my god

flat gazelle
#
In [4]: set.intersection?
Docstring:
Return the intersection of two sets as a new set.

(i.e. all elements that are in both sets.)
Type:      method_descriptor
``` you can use this, and use `set(some_iterable)` to create a set
frozen finch
#

i'm a little rusty on python but sets are akin to objects with key-values right

narrow kettle
#

That’s a dict

flat gazelle
#

{'bob', 'cat'} is also a set

frozen finch
#

oh right

flat gazelle
#

sets are similar to the mathematical set

#

every object is either in the set or not in the set. This check is O(1)

narrow kettle
#

They are unordered and unindexed

flat gazelle
#

elements must be hashable

#

strings are hashable

frozen finch
#

how is python this op lmao

#

i usually use JS but i can't believe how much functionality has already been implemented as functions python

grave jolt
#

JS also has sets

#

and Maps

narrow kettle
#

These are pretty standard language functions

flat gazelle
#

ye, most languages with standard libraries do indeed have these things

unkempt rock
#

hello

grave jolt
#

I still don't understand why you have to put new before a constructor in JS...

#

@unkempt rock This is a discussion channel

#

Please don't post links to help channels here

unkempt rock
#

oh okay

grave jolt
#

This is a discussion channel
Please don't post links to help channels here

unkempt rock
#

sure. can you take a look there

grave jolt
#

Be patient. If someone who knows selenium will want to help you, they will

#

(if it's about testing, of course)

unkempt rock
#

thanks

red solar
#
            while timeout >= 0 and not self.__is_locked:
                start_time = time.time()
                self.__is_locked = self.__sync_lock.acquire(False)
                await asyncio.sleep(0)
                timeout -= (time.time() - start_time)
#

is there a better way of measuring time elapsed than this?

#

(not that there's much wrong with it, just idk any other ways)

unkempt rock
#

I know that TCL(tickle) comes shipped with the prebuild python library. Why though? Its another language?

hollow crane
#

for tkinter

unkempt rock
#

I need help with sockets

#

Basically, I have this asynchronous function, and it is using epoll (a tcp listener that waits until a file descriptor is ready for I/O) and if I connect to the server for example on kitty or putty, and I hold down enter it starts spazzing out and the 'shell prompt' goes like everywhere, lemme show an example

#

How would I go around fixing this?

#

ah solely for making GUis?

hollow crane
#

yep

unkempt rock
#

I see

hollow crane
#

@unkempt rock what is the server hosted with

#

oh is it just ssh

unkempt rock
#

why print in the shell prompt?

hollow crane
#

what

unkempt rock
#

Why would you print one's file output to shell, sure its gets messyh

#

@hollow crane that's my own

#

send()

#

My server is hosted on digital ocean

#

your not ending te loop

hollow crane
#

what

unkempt rock
#

what

#

while(True)

#

that made 0 sense

hollow crane
#

yes

#

that's the point

unkempt rock
#

LOL

#

indeed

hollow crane
#

does this work

unkempt rock
#

yes

hollow crane
#

oh yeah it will won't it

unkempt rock
#

ok guess you figure it out urself then

#

it is supposed to be like that

hollow crane
#

ohh

#

ok good

unkempt rock
#

yea

#

I am very good with sockets but

#

this always confused me

hollow crane
#

wait so pressing enter on the client makes the response go all funny

#

does the server also see this

unkempt rock
#

no, when I hold enter

#

I want it to stay clean

hollow crane
#

nice sequential newlines?

unkempt rock
#

Like that

hollow crane
#

what's the server sending

unkempt rock
#

wdym

#

sock.send(self.config['Preferences']['prompt'].encode())

hollow crane
#

i've only seen that happen when the client automatically adds newlines

#

when you press enter

unkempt rock
#

it's not adding newlines

#
"prompt": "\\x1b[97m[\\x1b[91mcarlos\\x1b[97m@\\x1b[91mowo\\x1b[97m] \\x1b[37m"
#

I am fluent at C and I get the same issue there

hollow crane
#

so where are the newlines coming from

unkempt rock
#

From me pressing enter obviously

hollow crane
#

but who is sending them

#

my guess is your client (terminal window) is doing it automatically

#

but you say it isn't

unkempt rock
#

my code sends the pronpt

#

Prompt

#

Like I said epoll is a tcp listener

#

It binds to a port

#

Listens

#

Accepts

hollow crane
#

where did your code go

unkempt rock
#

Then you register the FD to epoll

hollow crane
#

ok...

unkempt rock
#

oh I will send it again sec

hollow crane
#

so your server never sends a newline?

unkempt rock
#

mhm

worldly venture
hollow crane
#

oh yeah

unkempt rock
#

ye

magic python
#

For some scripts i have it makes sense for there to be some method along the lines of run(), which could be put into if __name__ == '__main__', for some this wouldn't work though, as the method (say run()) requires and argument that isn't known in advance.

It seems that there's a fundamental difference between these two scenarios, to me, though I'm not sure what to refer to it as

#

is there? If so, how should I refer to these? (Is this the difference between a script and a module?)

raven ridge
#

the only difference between a script and a module is the intended usage - whether it's meant to be put on $PATH and executed directly by the user, or it's meant to be put on sys.path and imported from a scripted.

It's pretty common to see modules that have something like https://github.com/python/cpython/blob/master/Lib/json/tool.py#L76 - where the if __name__ == '__main__': block merely calls some function (usually called main), and that function looks at sys.argv to get any arguments that it needs.

magic python
#

where the if name == 'main': block merely calls some function

sure - but what if the function depends on input that isn't known before hand?

#

for example, suppose that there was some analysis carried out on different animal types, and the function would take input of the animal type, process('cat') or such

#

🤔 rather than just process()

#

to me, these seem like different use cases, but i wasn't really sure how to explain / differentiate between them properly

raven ridge
#

a script would take that as a command line argument, or possibly as an environment variable. A function can access either of those, from sys.argv or os.environ

magic python
#

right - but i could do

from . import animals

animals.process('cat')

or

from . import animals

animals.process()
#

these two cases seem different to me

hollow crane
#

but what's the second one meant to do?

#

normally modules take command line args

magic python
#

i don't know that is true

#

I have used modules a lot, just importing and running them?

#

so, not via the cli, just calling within python

raven ridge
#

@magic python those are normally just two separate functions in the same module. The module will have a main() that can be called with command line arguments, and its job is to parse them and call process('cat') or whatever based on the arguments it got.

magic python
#
if __name__ == "__main__":
    animals.process(cli_arg)
#

i'm getting the sense that there's no meaningful difference here

raven ridge
#

see https://github.com/python/cpython/blob/master/Lib/timeit.py#L375 for example - there's a if __name__ == '__main__': block that allows the module to be used as __main__. If it is, it just calls timeit.main(). timeit.main() parses the command line arguments, and based on them makes a call to timeit.Timer with various arguments.

magic python
#

yes - so that will catch the return call of the other script

#

0 for success etc

raven ridge
#

"other script"? There's only 1 script involved here, the timeit module

magic python
#

ok sorry - i've seen this used with an imported one before, this script sorry

raven ridge
#

yeah. there's no difference between a module and a script, other than how the user is meant to invoke them. When you do python foo.py, the interpreter loads foo.py in as a module called __main__. When you do import foo, the interpreter loads foo.py in as a module called foo. Pretty much the only difference between them is where the file is looked for.

magic python
#

all good - what i was saying seemed vague - i will review the code that you linked before though

#

why wouldn't someone use sys.exit( main() ) though?

#

I mean, why would someone just use main() instead of sys.exit( main() )

raven ridge
#

there's not much difference between them. the sys.exit() version will allow main() to return an integer return code or an error message if it wants to.

magic python
#

why wouldn't that approach be more standard though?

peak spoke
#

I'd expect most scripts to not have any special handling that would return non zero error codes

raven ridge
#

^ mostly just that, I think.

magic python
#

i don't seem to have seen it as often, but it seems more robust for some reason

#

@peak spoke they'd just have return 0 at the end of their main() i assume

raven ridge
#

if you aren't going to catch exceptions and map them to return codes, you may as well just have your main() not catch the exception at all, so that the process ends with a traceback if something fails.

peak spoke
#

If you get an exception or something that breaks your program, python quits nicely and will return the appropriate code

hollow crane
#

yeah python in general handles you not doing anything well

peak spoke
#

instead of you having to handle it all to return something meaningful in main

raven ridge
#

and if you're not going to return something special from main(), then there's no point in having the sys.exit call, assuming main() was already the last line of your __main__

magic python
#

If you get an exception or something that breaks your program, python quits nicely and will return the appropriate code

are you talking in general @peak spoke ?

#

hrm ok 🤔 maybe it's kinda redundant then, if there aren't also codes for 1 , 2 or whatever else there is (i only know 0 and 1 tbh)

raven ridge
#

there are no standardized codes except 0 meaning success. Everything else is application specific. And if Python ends with an exception, it already returns non-zero.

hollow crane
peak spoke
#

You'd have to map your own non zero codes for them to be useful

hollow crane
#

it just goes 'no' and explains why

#

if it can't run it as a module

magic python
#

@raven ridge right... so - oif 0 was the only code being used, it'd be kinda redundant

#

having 0 would change nothing in terms of any functionality

peak spoke
#

using sys.exit(...) is useful for example with qt that has a whole another system running along with python and returns a code in case something breaks there

magic python
#

i mean - having return 0 in main and sys.exit( main() ) , if 0 is the only code used, then it's kinda pointless it seems

#

@peak spoke does async stuff change anything here then?

peak spoke
#

It'd be the same as not doing it as python would have quit when reaching the end with 0

#

If it's pure python then not really

#

To get anything out of returned error codes you have to define handling for them, return the appropriate codes and then define those codes in your docs. The convention is just non zero if it didn't run successfully, which python already does

magic python
#

ok cool - thanks

signal bear
#

for some reason my dash buttons are not updaing my graph

#

and i can't seem to figure out why, I checked the docs, and stack overflow

#

i have no clue where to ask either

magic python
#

@signal bear have you tried creating a mwe and posting on stackoverflow

signal bear
#

mwe?

magic python
signal bear
#

k

#

im reading a post now that may be close

#

im burnt out

magic python
signal bear
#

i know how to use stack, just unfamiliar with the acronym mwe

red solar
#

do i need to declare methods in __slots__? does __slots__ have any effect on methods?

peak spoke
#

slots affects instance attributes

red solar
#

do methods count as instance attributes? (i wanna say yes, but not sure)

peak spoke
#

No, they're functions belonging to the class object that get bound when accessed from an instance

red solar
#

Slots are very useful for library calls to eliminate the “named method dispatch” when making function calls. This is mentioned in the SWIG documentation. For high performance libraries that want to reduce function overhead for commonly called functions using slots is much faster.

#

so then how does __slots__ have an effect on function calls?

magic python
lost nexus
#

so then how does __slots__ have an effect on function calls?
I don't think slots do have much of a direct effect with methods. like Numerlor said they only affect instance attributes.

lost nexus
#

when it comes to the Python GC, let's say I have a list of weak referents, however, the elements have a strong reference when the execution passes over them. If I remove the strong reference to the elements, are the elements destroyed right away, or do they get destroyed when an interaction is made with a list (which would bring the list back into relevancy?)

peak spoke
#

probably right away, or when the GC decides to run but it's not dependent on the list

lost nexus
#

when the GC decides to run
is the GC not going 100% of the time?

#

does it start when an object's refcount changes, or smth?

peak spoke
#

Well it's always running, but not always collecting because your actual code wouldn't run

#

Unless you disabled it that is

merry pollen
#

@lost nexus by default im fairly sure the refcount gc runs real-time

#

non-realtime refcounting is not super hot

#

and then the generational GC happens.... occasionally

#

™️

lost nexus
#

you disable the GC by setting all the generation thresholds to 0, ye?

merry pollen
#

uh

#

yeah im p sure

peak spoke
#

You can run gc.disable()

merry pollen
#

some libraries actually do gc.enable

raven ridge
#

Python's GC only gets involved when there's a reference cycle, because when objects are trapped in a reference cycle their reference count will never drop to 0. Most objects are collected when their reference count drops to 0 instead.

merry pollen
#

which is something to watch out for

lost nexus
#

what's a reference cycle?

raven ridge
#

For instance:

a = []
a.append(a)
``` And now you've got a list that contains itself.
#

There's other, much more subtle ways to make it happen, with multiple objects involved in the cycle instead of just one. But that's the simplest way.

signal eagle
#

yo i was sent here after asking a question in a python help channel. it regards taking addresses within a CSV file and creating a distance matrix with them via google maps api

#

if anyone thinks they can be of help, thatd be sick

raven ridge
#

That's definitely not on topic for this channel.

deft pagoda
#

this isn't a help channel

signal eagle
#

oh, the guy told me to come here, lol

lost nexus
#

if a is deleted with del, what happens to that reference cycle

signal eagle
#

im new to this

raven ridge
#

No worries! But we can't help with it here.

signal eagle
#

my apologies. thanks for the direction

raven ridge
#

@lost nexus the reference count of the list drops from 2 (a refers to the list and the list refers to the list) to 1 (the list refers to the list). Eventually the cycle collecting GC runs, traces all the references, detects that no variables refer to that list any more, and destroy it.

lost nexus
#

so the GC swoops in and destroys these for us?

raven ridge
#

Yep, that's the GC's purpose - to destroy objects whose reference count will never drop to 0.

lost nexus
#

would this prevent a reference cycle?

a = []
a.append(weakref.ref(a))
#

also, I thought the GC's purpose was to destroy objects with a refcount of 0. Is what you said just another thing that the GC does, or solely what it does?

merry pollen
#

there's both a reference-based collection system and a generational-based collection system

#

the reference-based one handles the things where refcount =0

#

and the generational-based one does the rest

#

broadly speaking i think most of the time reference counting isnt generally referred to as a GC

proud summit
#

@signal eagle sorry man, im new to this chat too

signal eagle
#

@proud summit ag

raven ridge
#

@lost nexus and "the GC" and the gc module refer only to the cycle collecting garbage collector.

#

The reference counting garbage collector cannot be disabled, and there's no way to interrogate its state (which is essentially just an int attached to each object)

lost nexus
#

so, virtually, there are two GC's. The reference-based one, and the generational-based one?

raven ridge
#

There are two ways that an object can be destroyed and its memory reclaimed: by its reference count dropping to 0 and by the cycle collecting garbage collector detecting that it's no longer reachable.

#

Only one of those is referred to as a GC, though, and it's the one that's only used to collect cycles

lost nexus
#

so the generational one is the only real GC?

raven ridge
#

Both collect garbage, but only one is an active process that occasionally runs in the background, and that's the one that people refer to as the GC

red solar
#

is the GIL an implementation detail, or can i rely on there not being data races in threads?

#

(in the sense that the GIL's mutex should synchronise the memory)

hazy anchor
#

You can still have data races with synchronised threads or coroutines, just not crashy ones

#

It's still possible to write erroneous code if they share references and don't take it into account

red solar
#

i mean more in the sense that the memory isn't as the previous thread left it

prime bison
#

does anyone work is GIS industry?

rich wharf
#

I find myself using a decorator for creating functions that take in values in loops

#

a decorator class

#
for i in range(3):
  @extend(i)
  def myfunc(i, x):
    print(i, x)
  myfunc(4)

Output

0 4
1 4
2 4
#

is there a better way to go about it?

rich wharf
#

A better way to use a value from the loop in a generated function?

brave badger
#

To be fair a simple function factory can do the trick

#

Which in this case can also be used as a decorator

rich wharf
#

@brave badger So my way of doing it is fine?

brave badger
#

It is fine imo

rich wharf
#

'ight

raven ridge
#

i mean more in the sense that the memory isn't as the previous thread left it
@red solar the GIL doesn't protect against data races. Create a global variable x=0. Make 10 threads that all call the same function. Make that function do global x and call x+=1 10,000 times each in a loop. Start all the threads. Join all the threads. Check the value of x. It will almost certainly be less than 100,000

#

That's because once in a while one thread will read and increment x, and before it can store the new value another thread gets swapped in and reads the old value of x for its next increment.

wild harness
#

is it dangerous to multiprocess a function which calls another recursive function?

rich wharf
#

you mean use multiprocessing to execute a recursive task?

wild harness
#

not exactly

#

or maube

rich wharf
#

that should be fine I think

#

as long as you give it a reference to the function

wild harness
#
def A(some args):
   #bunch of stuff
   B(some_more_args) #Recursive
   return something
rich wharf
#

B calls itself?

#

you'd probably need

#
def A(B):
  B()
  return something
wild harness
#
def A(some args):
   #bunch of stuff
   something = B(some_more_args) #Recursive
   return something

this is more like it

#

and B(some_more_args) is recursive

rich wharf
#
def A(B, some_args)
  ...
  return B(some_more_args)
#

that's just fine

wild harness
#

yeah

rich wharf
#

I don't see why it shouldn't work

wild harness
#

if multiple processes are running the same recursive function, is there a possibility of causing stack overflow?

rich wharf
#

nope

#

processes are separate

#

they'll each evaluate separately

wild harness
#

processes don't share the same stack, but they get that memory from some global pool right

#

is it possible that all the processes combined might use up the available memory?

rich wharf
#

I'm not sure, I think each process takes up as much space as it needs to but I don't know about memory management

#

It might, I'm not sure

#

But they will not share any variables, @wild harness

wild harness
#

hmm

rich wharf
#

The process only takes in the args you give it in the function call

wild harness
#

i see

rich wharf
#

@wild harness have you heard of pickle?

#

it's a python library that serializes python objects to strings and can reevaluate them in other processes

#

essentially, multiprocessing uses pickle to convert your args to strings and passes them to the other process, then converting them back, @wild harness

#

that's why you have to pass in B as an argument

hazy anchor
#

Processes can leverage copy on write memory to an extent

#

Calculating their total memory use before hand is not trivial

wild harness
#

essentially, multiprocessing uses pickle to convert your args to strings and passes them to the other process, then converting them back, @wild harness
@rich wharf thanks!

rich wharf
#

np

undone hare
true hollow
#

Why the Python Interpreter require us to only use tabs or only spaces? TabError is really finicky and in my opinion an useless exception

undone hare
#

Because of the way the parser is designed I think

flat gazelle
#

because tab width is not clearly defined

#

so what looks like

    if True:
# ^ 4 spaces    
        print('Hi')
# ^ 8 spaces
        print('Bye')
# ^ tab, in editor defined 8 spaces wide
    if True:
# ^ 4 spaces    
        print('Hi')
# ^ 8 spaces
    print('Bye')
# ^ tab, in editor defined 4 spaces wide
```different code, same characters
true hollow
#

hm seems legit

lost nexus
#

is willingly creating a reference cycle a bad practice?

hazy anchor
#

In some instances it's not avoidable

#

As long as you make the appropriate points a weak ref it's a moot point

#

E.g a double linked list

lost nexus
#

so

a = []
a.append(weakref.ref(a))

is better than

a = []
a.append(a)

?

hazy anchor
#

You'd not do either of those but if for some reason you had to, all the inner references could be weak

lost nexus
#

It's an example and alright then

hazy anchor
#

A doubly linked list is fairly intuitive and not that rare, implement one as a test

undone hare
#

I'm pretty certain that CPython does some reference tracing cycles anyway to catch cycles

unkempt rock
#

What packages of python should i use to combine c and mysql?

#

I just wanted to make an os for that they said we need high level language and low language

#

Thats why

lost nexus
#

are there any container types that remove objects in a FIFO order if a max size is reached?

hazy anchor
#

Really just a cache

#

Most have pluggable eviction strategy, LFO being most common but fifo is trivial

lost nexus
#

I know, but are there any types that do this already?

hazy anchor
#

Not to my knowledge. What you're describing is merely a cache

#

Obviously you could just implement one with a stack or a queue yourself

#

But it would probably suck compared to your normal dict based cache

old sun
#

@lost nexus collections.deque?

lost nexus
#

deque is FIFO when max size is reached?

hazy anchor
#

It could be, but it depends on the access pattern

#

No use using a queue/deque if it needs key/lookup functionality, which I typically associate with anything that uses evictions.

lost nexus
#

I don't need lookup functionality thankfully here

#

also, what method is called when a deque is subscripted. is it __getitem__?

hollow crane
#

i assume so

lost nexus
#

and does appending an element call __setitem__

spice pecan
#

__setitem__ is called when you access an element by index and set a value to it, ie
obj[index] = value is equivalent to obj.__setitem__(index, value)

#

Appending a new element is usually done without __setitem__, but nothing is there to stop you from allowing to append elements via __setitem__ in your class

#
class MyList(list):
    def __setitem__(self, index, value):
        if index == len(self):
            self.append(value)
        else:
            super().__setitem__(index, value)
#

something like that should work

spark magnet
#

i wouldn't recommend subclassing list

lost nexus
#

elaborate?

spice pecan
#

It's just an example, obviously

deft gyro
#

😦

primal magnet
#

?