#internals-and-peps

1 messages Β· Page 117 of 1

flat gazelle
#

also, why are we not using {int: int} and [int] for type hints? It seems a bit nicer

magic python
#

the weight sums aren't looked up no

halcyon trail
#

if you don't do lookups on them, then why are they keys in a dict

flat gazelle
#

are you sure you don't just want a sequence of tuples?

magic python
#

the weighted sums aren't keys in a dict

#

they are values in a dict

flat gazelle
#

sometimes the keys are floats not ints
why?

halcyon trail
#
Mapping[ Tuple[Union[float, int], Union[float, int]], int]
grave jolt
halcyon trail
#

Here, the key of the dict is Tuple[Union[float, int], Union[float, int]]

#

so you could have e.g. a pair of floats as a key into a dict

flat gazelle
#

makes sense

magic python
#

because sometimes they are - this is what's received, this is metadata which relates to the values that are stored in the data though, if there are Nans in the data then maybe sometimes that makes the column into float rather than int πŸ€”

It might be possible to enforce that the tuples have ints instead of floats or ints, but it seems odd still

#

@flat gazelle re your question πŸ‘†

flat gazelle
#

I see

halcyon trail
#

why not List[Tuple[Union[float, int], Union[float, int], int]]

flat gazelle
#

well, if you want union typed keys, you can't use non union typed keys before

halcyon trail
#

it's the exact same data

magic python
halcyon trail
#

The only difference between the two is that the Mapping/Dict approach gives you fast lookups on the key, but you can't do those correctly anyway on a floating point number, and it's not clear if you are doing that

magic python
halcyon trail
#

it's the key in the nested dict...

#

no matter how you slice it, with the type that you have, floating point numbers can end up as keys into a dict

magic python
#

sure - i don't really mind that

#

i'm not bothered about optimisations here

halcyon trail
#

it's not optimization

#

it's correctness

magic python
#

{1.0 : 'something'} works tho

halcyon trail
#

it works but there's no guarantee that x = { (0.3 + 0.7): 'something'}; x[0.7+0.3] will work

magic python
#

I'm not doing addition on it

halcyon trail
#

if you're just copying the number around to look up later, and not doing anything else with it, then it should be easy to use something else as the key πŸ™‚

magic python
#

it should be easy to type hint something with a fixed structure too πŸ™ƒ

halcyon trail
#

it is easy, we already explained how to do it

#

it's just awkward because it's an awkward structure

magic python
#

i ended up with loads more errors and just used any, but sure, easy

halcyon trail
#

I literally copy pasted the annotation from the function to the variable:

y:  Mapping[ Tuple[str, str], Mapping[ Tuple[Union[float, int], Union[float, int]], int] ] = { ('a', 'b') :  {(1, 1): 2, (2, 3): 1} }
def g( k : Mapping[ Tuple[str, str], Mapping[ Tuple[Union[float, int], Union[float, int]], int] ] ):
    print(k)
    

g(y)
#

so yeah, seems pretty easy

magic python
#

@halcyon trail it then triggers loads of errors elsewhere, it's pretty annoying to have you try and insist everything i'm doing is wrong, have a long thread with back and forth with people who are well informed, for you to then sum it as easy

#

if it was then it would have been done from the start, but it wasn't, unless you're using some stupid academic interpretation of the word easy where a load of work is done then the result is "obvious"

halcyon trail
#

I don't know anything about the errors you're getting elsewhere, I can't diagnose code I haven't seen

#

Like I said, I wrote "annotate y explicitly" very near the start of this conversation πŸ€·β€β™‚οΈ

#

it solves the problem you posted

steel lagoon
#

where do i ask about amateur questions lol

mild flax
fast warren
#

Im making quantum circuits ^_^

static bluff
#

Cool, trying this again

#

XD

#

I remember in another project, I had a class that was used everywhere and every time I started from a blank slate I'd rewrite it or at least give it a once over

#

I eventually came down from 200 lines to about 30

fallen slateBOT
unkempt rock
#

lmao

#

high performance fizzbuzz

#

if you want to get higher performance fizzbuzz you need cython

#

or I'm stupid

#

which is correct

#

Can bool(type(some_object)) ever return False (without renaming built-ins) MHXThink

#

!e Never mind, it can thanks to @native flame ```py
class Meta(type):
def bool(self):
return False

class A(metaclass=Meta):
pass

print(bool(type(A())))```

fallen slateBOT
#

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

False
unkempt rock
#

Can u help me with this question
WAP to calculate simple interest where R, T and P are entered by the user

visual shadow
dusk prism
#

hey so does anyone know how to make a python file execute another python file (not just open the text editor of the file) ```
def run(filename):
os.startfile(filename)

run("file.py") ```

magic python
devout locust
#

WHICH is best code editor Sublime text or Vs code

I use Sublime text for 3 years can I still continue with it or move to vscode:heart_eyes

dusk prism
safe hedge
verbal escarp
#

just wondering, why is it considered "best practice" to return None if a function modifies something in place instead of returning the changed object, even if you could easily document that behaviour?

halcyon trail
#

Because that way functions do one thing or the other, create a new object they return, or mutate in place, not both

tawdry ruin
halcyon trail
#

And from the usage you can see which it is

tawdry ruin
#

will run the code

verbal escarp
#

@tawdry ruin eh?

halcyon trail
#

And there aren't, "surprise mutations", e.g. when you do y = foo(x), you don't want x getting mutated usually

tawdry ruin
#

nothing sry

verbal escarp
#

@halcyon trail but if you return the changed thing, you could have a conveyor belt style code..

#

which would integrate better with other code

safe hedge
#

What do you mean by that?

#

Do you mean a more functional style programming with pipes?

verbal escarp
#

something like that, yes

safe hedge
#

I'm not sure how:

mylist.alter()
mylist = mylist.alter()
#

Make much difference to that

verbal escarp
#

although i'm aware that functional style relies on immutable objects

#

is there some theoretical background for this restriction or is that just to enforce convention?

charred pilot
#

maybe he's talking about a fluent api type thing, like chaining methods

safe hedge
#

You can chain methods though...

#

If they don't mutate in-place

verbal escarp
#

@charred pilot yeah, something like that

safe hedge
#

And I think some libraries do do what he is stating

#

I think maybe pandas?

#

Certainly I'm sure I've come across this. But @halcyon trail is right that by having a "mutating" method return None rather than the object there is less ambiguity about what is happening

#

And it fits with the Zen of Python - "There should be one-- and preferably only one --obvious way to do it."

#

So that's probably a big part of stdlib things not being like that

verbal escarp
#

"there should be one and preferably only one obvious way" is one of the zens that are least honored in python πŸ˜‰

safe hedge
#

But the point is that this adheres to that in a way

#

So it's kind of unsurprising to me

verbal escarp
#

i see what you're getting at, so it's about avoiding surprises

safe hedge
#

If I have an assignment like so:

newlist = oldlist.append(x)

Someone who isn't up to speed might assume that oldlist is unchanged

verbal escarp
#

coming from a functional style language, possibly, yes

safe hedge
#

Admittedly under your system you don't have to reassign, but it just creates unnecessary trip-ups

halcyon trail
#

@verbal escarp that's fine, if you want chaining don't mutate the argument?

#

Btw

#

The "theoretical" background

gleaming rover
#

I believe there are languages

#

which have operators just for that

grave jolt
#

isn't using x++/++x as expressions basically breaking CQS?

gleaming rover
#

e.g.

egg..crack()
   ..fry()
   ..plate()
   ..serve()

is the same as

egg.crack()
egg.fry()
egg.plate()
egg.serve()
halcyon trail
#

Cqs isn't a hard rule

#

And python doesn't have ++

#

A few python collections have pop though

#

Which violates cqs

verbal escarp
#

hm.. food for thought πŸ™‚

halcyon trail
#

Also if you like left to right chaining, python is sadly pretty deficient in this area

verbal escarp
#

i really enjoy method-chaining though in many cases

charred pilot
#

especially for iterators, like with linq in c# or streams in java

halcyon trail
#

Yeah, I mean enjoy it too, python just doesn't have great tools for it

#

You should check out Kotlin though, it has some amazingly slick tools in that regard

charred pilot
#

rust too

verbal escarp
#

can you give an example of what is possible there that isn't in python?

unkempt rock
#

How do i design my own desktop environment in Debian and arch linux?

halcyon trail
#

Kotlin has extension functions, so you can define fun tions from outside the class that follow member syntax

#

Which allows chaining

#

You can also just change arbitrary functions using a scope function

#

foo.let { bar(it, 5) }.let { baz(7, it) }

#

You can also repeat mutators without repeating the object name

#

In python you'd do

foo.mutate()
foo.mutate2()
foo.mutate3()
#

In Kotlin you can do:

foo.run {
   mutate()
   mutate2()
   mutate3()
}
verbal escarp
#

hm.. but foo.mutate().mutate2().mutate3() would be even cleaner

#

or maybe pipe semantics?

#

but that's not mutating an object really by default i guess

#

difficult..

halcyon trail
#

Well, that .let is pipeline semantics basically

verbal escarp
#

yeah, i get it

#

a bit verbose though

halcyon trail
#

Well worth it to not have to introduce special syntax/operator

#

Most things that are obvious candidates for this sort of thing are already written as extensions, keep in mind

verbal escarp
#

thanks for the feedback πŸ™‚

halcyon trail
#

Np

#

The main time the python situation bugs me is when I want to chain iterators

#

Just feels so clumsy

verbal escarp
#

yeah, i can see that

flat gazelle
#

yeah, the cleanest option python really has are generator functions

halcyon trail
#

Generators are nice

#

Everyone stole them though :-)

flat gazelle
#

yup

#

though few have generator coroutines (which admittedly arent super useful in these cases)

halcyon trail
#

Now that I think of it, it's one of the few ideas that python can really claim to have popularized that has been widely stolen

visual shadow
#

Was unpacking prevalent before python?

flat gazelle
#

decorators are also somewhat prevalent now

#

unpacking is weaker patma

#

which really starts with prolog/SML/math

visual shadow
#

I wouldn't call unpacking as just patma, since it's so narrow in focus that makes it super accessible

halcyon trail
#

Decorators aren't that prevalent

visual shadow
#

Like a precision screwdriver as opposed to the entire toolkit

halcyon trail
#

The @ that some languages have isn't much like decorators

flat gazelle
#

ye, IG it is just typescript from the important languages

halcyon trail
#

Unpacking may also be a good example

#

Trying to think who else had it

flat gazelle
#

actually, LISP has had unpacking for a very long time with destructuring-bind

halcyon trail
#

Early

#

Yeah was thinking about lisp but lisp was never popular

#

I mean python didn't invent generators either

visual shadow
#

I don't know what's the current state of looping in other languages. Is it popular to only provide "for each" style of for loops in languages today?

flat gazelle
#

python may have actually popularized range iterators

visual shadow
#

That was something that I thought was rather unique coming into python. Not just the fact that there was a for each loop, but specifically forgoing an index based loop in favour of just "for each"

flat gazelle
#

I think most languages still keep the 3 form for loop in some form, but range iterators are definitely quite prevalent

#

but also, functional languages, apl etc did it first

visual shadow
#

Aye. Ultimately python was an amalgamation of great ideas before it.

grave jolt
#

JavaScript has 3 types of for, and the for-in is pretty much never useful

#

for-in iterates over the keys of an object, and for-of iterates over the elements of an iterable

visual shadow
#

Sounds like then "for of" is essentially what python loop would be like in that context.

grave jolt
#

yes

visual shadow
#

Okay. What about things like tracing? Though I suspect this probably didn't catch on since I assume (am I mistaken) that tracing is not really a thing in compiled languages?

halcyon trail
#

Tracing?

visual shadow
#

I mean stuff like settrace, where you're able to inject code on each line execution to do additional stuff

halcyon trail
#

Not sure this is really in the same vein as previous examples

#

This is a metatool for writing tooling like code coverage, etc and not much else afaik

flat gazelle
#

it is an interesting question if python introduced any new category of tooling

#

I am willing to guess static external type checker are a novel thing, though similar tools do exist for C

halcyon trail
#

I'm not sure you can call it a novelty for being.bolted on

flat gazelle
#

python is far from the first language to have linters which are far stricter than the language itself, but I think it is the first to have a whole type system in this way

#

that is mostly an implementation detail

verbal escarp
#

what about optional typing?

#

i've never heard about that before python

flat gazelle
#

Gradual typing is a very old thing, yes. The interesting idea of python is that the type checker is independent of the language

halcyon trail
#

i really don't view it as an interesting thing, tbh. It's more of an evolution in an existing language, trying to keep everyone happy

#

rather than a good feature to design into a new language

#

which is a reasonable characterization of things like generators, destructuring, ranged for

flat gazelle
#

@unkempt rockplease avoid posting memes without any context

halcyon trail
#

In python pathlib, .exists() for a symlink checks if the target exists

#

how does one check if the symlink itself exists?

#

in os.path I think this woudl have been lexists

prime estuary
#

You could just use the os.path function with the path, which seems reasonable enough for such a rare operation.

finite sparrow
#

i think in this case the explicit way would be best: path.readlink().exists() to check whether a symlink destination exists

halcyon trail
#

@prime estuary yeah that's what I did

#

@finite sparrow Path.exists is the same as path.readlink().exists(), I think

#

in both cases you're checking whether the symlink's target exists

#

I guess readlink might throw an exception if you try it on a non-existent symlink

finite sparrow
#

oh guess i didnt notice the note for path.exists

halcyon trail
#

yeah, it's a bit silly IMHO, for exactly this reason

unkempt rock
#

!e Is there rationale for this giving a TypeError rather than a ValueError? py float(1.0, 2.0)

fallen slateBOT
#

@unkempt rock :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: float expected at most 1 argument, got 2
unkempt rock
#

Seems like either could make sense pithink

grave jolt
#

!e

def f(x, y, z):
    ...

f(1, 2)
fallen slateBOT
#

@grave jolt :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 4, in <module>
003 | TypeError: f() missing 1 required positional argument: 'z'
unkempt rock
#

I know. But why is TypeError more fitting than ValueError?

bitter scroll
#

Does anyone know if it is possible to limit RAM usage to an application made in python (not compiled, i.e. from the interpreter)?

raven ridge
grave jolt
#

maybe there should've been a special WrongArgumentCount exception or something like that

raven ridge
#

would it subclass TypeError or ValueError? πŸ™‚

grave jolt
#

why?

raven ridge
#

oh, you're imaging greenfield, not proposing a future direction. I see.

grave jolt
#

yeah

#

I suppose the logic is that in a statically typed language, you'd get a compile error if you called a function with the wrong number of arguments

raven ridge
#

usually a TypeError indicates that an argument was the wrong type for a callable, but in this case it indicates that a callable was the wrong type (arity, really) for an argument

#

it's backwards from normal, but still makes reasonable sense if you squint.

grave jolt
#

πŸ€”

#

yeah, sort of

raven ridge
#

the logic may have just been "it's a bit strange, but it's not worth creating a new exception type for it" πŸ˜„

grave jolt
#

I guess it makes sense in the sense that TypeError is raised when some operation isn't supported, like + or <

#

...and when it's the programmer's fault

raven ridge
#

not if you call < with the wrong number of arguments! brainmon

#

!e 5 <

fallen slateBOT
#

@raven ridge :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 |     5 <
003 |        ^
004 | SyntaxError: invalid syntax
grave jolt
#

lol

fallen slateBOT
#

@grave jolt :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: expected 1 argument, got 3
grave jolt
#

actually, you get a TypeError as well!

#

that space before . is very important.

#

although I think it's a bug in the parser

unkempt rock
#

Need a PEP to change it to ArityError and break loads of stuff ducky_devil

#

Woah, I didn't know you could space like that. I've been doing (2).thing

#

!e py print(3j .conjugate())

fallen slateBOT
#

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

-3j
faint quail
#

in a function, should you raise an error if the user puts bad arguments in, or should you let the errors crop up when something naturally goes wrong because of it?

raven ridge
#

there's valid arguments for either approach, though letting the errors crop up naturally tends to both be less work and have better performance

#

I usually only try to catch the mistake and warn early when a) it's a mistake that I expect, and b) the error that they get if they make it won't be easy to understand

grave jolt
#

let the errors crop up when something naturally goes wrong because of it?
This approach also has a potential of the error never ocurring in your code, instead giving out some garbage value

#

All those "Fresh apples for the low price of $NaN.undefined" moments

faint quail
#

okay, yeah, makes sense

raven ridge
#

there are also certain errors that can only be detected after the fact

grave jolt
#

Yeah, for example, a binary search function might expect a sorted list.

#

But if it checked if the list was sorted, it would be very silly

raven ridge
#

Or, the first argument to os.remove() must be a path to a file that exists on disk. Checking that in advance isn't useful, because the file could just be removed by someone else after you check and before you try to remove it.

dusk prism
#

i finally figured out how to run a program in a new command window and not the text editor or appending it to another program etc.

#

subprocess.call('start /wait python filename.py', shell=True)

#
subprocess.call('start /wait python bb.py', shell=True)```
ocean ravine
#

How can i run functions in parallel?

I use β€˜requests’ to GET 30 requests every 3 seconds. For a thought i wondered if it was possible to run 15 in a thread and the other 15 in another thread?

#

As mutlithreading is new to me. I’d love to hear your advice.

merry trench
radiant fulcrum
#

Concurrency ! = parallel

#

Threading in python is concurrent same with asyncio

#

Multiprocessing is parallel becauses its multiple instances of the python process running

#

In this case it doesnt matter much because waiting for IO can be done concurrently to make better use of resources but it wont be parallel in the literal term

paper echo
gleaming rover
halcyon trail
#

sounds like a good friend of little bobby drop tables

unkempt rock
#

does iter = PyObject_GetIter(iterable) consume the iterable if it's a generator?

peak spoke
#

I think that'll just return self

paper echo
#

is PyObject_GetIter() the same as iter()?

peak spoke
#

!d PyObject_GetIter yes

fallen slateBOT
#

PyObject* PyObject_GetIter(PyObjectΒ *o)```
*Return value: New reference.*This is equivalent to the Python expression `iter(o)`. It returns a new iterator for the object argument, or the object itself if the object is already an iterator. Raises [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError "TypeError") and returns `NULL` if the object cannot be iterated.
unkempt rock
#

Does the __str__ dunder really need to exist? (Except out of convenience and backwards compatibility) It seems like it could always call format with no format_spec (aka empty string format_spec)

#

Like is there a drawback to having py def __str__(self): return format(self) assuming your __format__ exists and is written sanely

spark magnet
unkempt rock
#

Yeah

#

I guess I'm wishing __str__ would default to format if you didn't define it

#

!e but it doesn't sad py class C: def __format__(self, format_spec: str) -> str: print("formatting") return "FLOOF" c = C() print(c, str(c), format(c))

fallen slateBOT
#

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

001 | formatting
002 | <__main__.C object at 0x7fc4227b7ee0> <__main__.C object at 0x7fc4227b7ee0> FLOOF
dusk prism
spark magnet
dusk prism
#

Oops

#

Either way it still works

raven ridge
#

The only basis I can think of for rejecting that is that it would make str a bit slower for types that neither define __str__ nor __format__ but instead inherit them from their parent class.

unkempt rock
#

How does one go about proposing something like that? discoHmm Seems such a tiny change for a whole PEP.

deft pagoda
#

python-ideas maybe

#

but you might define a __format__ where an empty spec errors or something

prime estuary
#

Yeah, usually you propose it there, if other people like it, you might be directed to open an issue and get it patched there.

#

Python 3.10 is in beta now, so no more features are added - so it'd be 3.11 at earliest if liked.

#

You definitely want to check if there's any backwards compatibility issues - say, what if a parent class does define format but not str, performance issues, and also if you're able to do the work to implement it that's a big plus.

sand python
#

__format__ defaults to using __str__ though, so I don't think it is possible to change without breaking things?

#

!e ```py
class A:
def str(self):
return "this is A"

print(format(A()))

fallen slateBOT
#

@sand python :white_check_mark: Your eval job has completed with return code 0.

this is A
prime estuary
#

That can be resolved by object.__str__ checking if obj.__format__ is object.__format__ or something.

unkempt rock
#

is there any alternative to pyarmor?

merry trench
#

one simple question please help. what happens if I don't write __init__(): manually inside a class? does it call default constructor by itself?

raven ridge
#

The class inherits the __init__ of the next class in its MRO

merry trench
#

i am sorry but didn't understand this part: "next class in its MRO"

#

can you please elaborate little bit?

prime estuary
#

If you don't define it, the superclass's method is called.

#

The "Method Resolution Order" refers to the specific order superclasses is checked in, which can get complicated if something inherits from multiple things, or say the parent inherits from a grandparent, etc.

prime estuary
visual shadow
#

No i think they're asking what happens if they don't write an init in a class at all. To put it simply, yes it's fine nothing bad happens as such because it does use the default init of its parent. (hence the mro). All classes implicitly have a parent called Object so that init is used

merry trench
#

oh. i get it now. so if i need to pass some attributes to set while creating an object only then I need to define init otherwise not actually necessary right?

visual shadow
#

Yes. Though classes without an init sound rather pointless for the most part.

merry trench
#

yeah. just confirming the workflow of init. thank you guys a lot.

raven ridge
#

They often have completely empty class bodies.

fallen slateBOT
#

Lib/asyncio/exceptions.py lines 9 to 18

class CancelledError(BaseException):
    """The Future or Task was cancelled."""


class TimeoutError(Exception):
    """The operation exceeded the given deadline."""


class InvalidStateError(Exception):
    """The operation is not allowed in this state."""```
visual shadow
#

Those inherit from an Exception class though. I suppose I was taking the shorthand by not explicitly stating it. (ie, thinking of only normal classes without an init, no inheritance)

prime estuary
#

Well they still inherit, just from object which has an entirely blank init.

visual shadow
#

oh

#

i see. didn't know that.

spark magnet
#

posting this in multiple channels is starting to seem like spam

magic python
fallen slateBOT
#

example/example_conftest.py lines 19 to 23

def collect_types_fixture():
    from pyannotate_runtime import collect_types
    collect_types.start()
    yield
    collect_types.stop()```
fallen slateBOT
#

example/example_conftest.py lines 10 to 12

Explicitly delay importing `​collect_types`​ until all tests have
been collected.  This gives gevent a chance to monkey patch the
world before importing pyannotate.```
sacred tinsel
#

the same reasoning probably applies to all the funcs

magic python
fallen slateBOT
#

fastentrypoints.py lines 92 to 98

def main():
    import os
    import shutil
    import sys

    dests = sys.argv[1:] or ["."]
    filename = re.sub(r"\.pyc$", ".py", __file__)```
magic python
#

idk why you'd delay importing os, shutil, sys though

spice pecan
#

perhaps they just don't want them to be available in the module, for whatever reason

magic python
true ridge
#

Perhaps not for modules like os, sys etc. (since %99 of time, the python startup uses them through site) but if you are importing complicated modules (e.g aiobotocore, which takes about 0.4-0.5 seconds on my computer just to import), or if you have some complicated logic in the top-level code (e.g creating a dictionary with bunch of items to be used as cache) then it makes sense to conditionally import those modules under the functions which actually use them so you'd defer the cost from startup time to actual usage. This is a very important practice for the short-running commands (e.g cli applications)

grave jolt
#

which takes about 0.4-0.5 seconds on my computer just to import
πŸ‘€ why

flat gazelle
#

probably just a lot of code, dataclasses are also famously guilty of this

magic python
unkempt rock
#
result =  c**3 + d**3 
append (c, d)  to  list at  value map[result] 

how would u do this in Python?

#

is this a defaultdict(list) situation?

raven ridge
unkempt rock
raven ridge
#

I'm not sure what you're asking. Both using defaultdict and using dict.setdefault seem easy enough to me.

unkempt rock
#

what's the defaultdict way?

#

I'm a bit confused, the defaultdict(list), list is the value not the key?

raven ridge
#
from collections import defaultdict
map = defaultdict(list)
map[result].append((c, d))
#

the key is the same thing either way - result

unkempt rock
#

the key is result?

raven ridge
#

yeah - you said you wanted to store it into a list at map[result], so result is the key and the list is the value

sacred tinsel
#

in that case list the built in

#

it's the same as defaultdict(lambda: [])

raven ridge
#

right, list is the default value for the default dict, because calling list() returns a new, empty list to use as the starting value for missing keys

unkempt rock
#

thanks I understand

#

what is list=map.get(result) in Python?

#

dict[result]?

raven ridge
#

map.get(result) is like map[result], except if map has no result key, then it returns None

signal tide
#

dict.get(key, default) dict[key] if key in dict else default

signal tide
unkempt rock
#

interesting, Python has a lot of stuff I didnt know

#

what's
append (c,d) to list at value map[result] in Python?

#

dict[result].append((c,d))?

#

nvm I think it's same

#

"to list at value" part confused me

signal tide
#

does .get() call __getitem__ or does it go through something else?

raven ridge
signal tide
#

what other types support it?

raven ridge
#

all mappings

fallen slateBOT
#

Lib/_collections_abc.py lines 759 to 764

def get(self, key, default=None):
    'D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.'
    try:
        return self[key]
    except KeyError:
        return default```
signal tide
#

idk how but I completely forgot about collections

signal tide
raven ridge
fallen slateBOT
#

Objects/dictobject.c line 2880

ix = _Py_dict_lookup(self, key, hash, &val);```
`Objects/dictobject.c` line 2065
```c
ix = _Py_dict_lookup(mp, key, hash, &value);```
signal tide
#

huh neat the lookup's a lot more complex than I thought it'd be

unkempt rock
#

how would u write that second part in Python?

#

I just wish the book was written in Python ;\

#
>>> for key, val in dicti:
...     for pair1 in val:
...             for pair2 in val:
...                  print(pair1, pair2)
``` but this is wrong
round kiln
#

dicti.items()

unkempt rock
#

thx

raven ridge
#

it would just be:

for key, val in dicti:
    for pair in val:
        print(pair)
unkempt rock
#

.items()?

round kiln
#

iterating over a dictionary without specifying .items() just returns the keys, not the values

raven ridge
#

ah, oops, yeah

#
for key, val in dicti.items():
    for pair in val:
        print(pair)
#

or

for val in dicti.values():
    for pair in val:
        print(pair)
#

if those don't work, it's because you've appended something other than a pair of values to the list.

unkempt rock
#

in my original code isn't pair1 and pair2 wrong anyway?

#

they need to be val[0] and val[1] ?

#

my complete code:

>>> n = 5
>>> for c in range(1, n):
...     for d in range(1, n):
...             result = c**3 + d**3
...             dicti[result].append((c,d))
>>> for key, val in dicti.items():
...     for pair in val:
...         print(pair)

but it seems to not be doing the correct thing.

raven ridge
#

that should work.

#

what goes wrong?

unkempt rock
#

the point of the problem is "Print all positive integer solutions to the equation a**3 + b**3 = c**3 + d**3 where a, b, c and d are integers between 1 and 5."

raven ridge
#

you need n+1 instead of n in the range call, then.

round kiln
#

uninitialized keys. so either (1) check if the key exists and add if it does not. or (2) initialize dicti using collections.defaultdict(list)

raven ridge
#

!e ```py
from collections import defaultdict
dicti = defaultdict(list)
n = 6
for c in range(1, n):
for d in range(1, n):
result = c3 + d3
dicti[result].append((c,d))
for result, list_of_pairs in dicti.items():
for pair in list_of_pairs:
print(result, pair)

fallen slateBOT
#

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

001 | 2 (1, 1)
002 | 9 (1, 2)
003 | 9 (2, 1)
004 | 28 (1, 3)
005 | 28 (3, 1)
006 | 65 (1, 4)
007 | 65 (4, 1)
008 | 126 (1, 5)
009 | 126 (5, 1)
010 | 16 (2, 2)
011 | 35 (2, 3)
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/icironapug.txt?noredirect

unkempt rock
#

I see that makes sense

#

if I wanted to print all ints a, b, c, d that satisfied a^3 + b^3 = c^3 + d^3
would it still be the same as above?

#

I mean are the pairs on both sides identical?

#

or I guess they dont have to be

#

I guess it's either it or its mirror version like (1,2) and (1,2) or (1,2) and (2,1)

marsh carbon
summer hedge
#

Can someone ELI5 when to use WSGI vs ASGI webservers? For instance I'm building a discord bot that would have direct access to a database. So it'll probably be some custom DAL using asyncio. It'd be great to split that DAL into a package and use it on a web front end as well that acts more than just for a discord bot. But then I would need ASGI server? Are there disadvantages to a community website using purely ASGI?

finite sparrow
#

generally ASGI is the newer protocol, the A stands for asynchronous. That means generally ASGI will be easier to integrate directly into a discord bot, since both are async. There really isn't much of a advantage WSGI has over ASGI, other than the frameworks are way more mature and stable (less breaking updates, generally less bugs, easier to maintain) and somewhat easier to use (in my experience) at the cost of lower performance. I would say it doesn't really matter which you choose, your choice of framework is much more important. Do you want to make a API backend for a JS frontend? probably FastAPI (ASGI). Is your project gonna be big and backend-rendered? Django (WSGI). Would you rather go microframework which means less setup and easier to learn if less powerfull? Flask (WSGI)
(the framework usecases and recommendations are of course my personal opinion)

summer hedge
#

Any opinions on Tornado vs Fast API?

#

Not really planning a rest api... although one layer could have it

#

it'll probably be more server rendered for SEO

finite sparrow
#

Tornado is old, and not something that you should make a new project in, imo.

summer hedge
#

Thanks. Looking at FastAPI

grave jolt
#

If you want to learn how ASGI works, I'd recommend looking at Starlette

#

FastAPI is based on Starlette, but it itself is a fully capable framework

verbal escarp
#

sigh. anyone care to give any useful input? i've posted in three different channels now with no answer

#

i'm working on the auto-install feature of https://github.com/amogorkon/justuse, where you would use("package", auto_install=True) and it would return a useful exception with some info about the package you are trying to install. now my question is what info i should give the user for them to decide whether or not the package may be malicious or not

#

i was thinking of download count, but that's all i came up with

true ridge
#

It is nearly impossible to 'figure out' whether a package is malicious or not in the exact sense, but there have been various scoring systems which you could use as some sort of threshold to whether ask for confirmation or not. An example is the Snyk's health score metric, which is composed from various factors (how many contributors you have, install count etc.). See an example here: https://snyk.io/advisor/python/fsspec

verbal escarp
#

@true ridge finally some sensible input, thank you

magic python
peak spoke
#

poetry may be more fitting, but pipenv still works mostly fine and is managed by the PyPA

magic python
undone hare
#

They both have their strengths and weaknesses tbh

#

I don't think one will become more standard than the other

magic python
undone hare
#

I don't think it applies to tools and libraries - diversity in both is important

unkempt rock
#

1 + 1 = 10

unkempt rock
#

Hey

#

i m looking dor a modelisation of vaccination effect in SIR MODEL

#

but with the determinist model

#

with no markov chn etc

peak spoke
fallen slateBOT
#

Objects/object.c lines 1435 to 1443

PyObject_IsTrue(PyObject *v)
{
    Py_ssize_t res;
    if (v == Py_True)
        return 1;
    if (v == Py_False)
        return 0;
    if (v == Py_None)
        return 0;```
raven ridge
#

If it didn't, bool(None) would be False but type(None).__bool__(None) would be True

#

that doesn't seem desirable

peak spoke
#

type(None).__bool__ wouldn't this be an invalid lookup?

raven ridge
#

why would it be?

#

it's inherited from object

peak spoke
#

!e object.__bool__

fallen slateBOT
#

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

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | AttributeError: type object 'object' has no attribute '__bool__'
raven ridge
#

huh. I did not know that...

boreal umbra
#

General question: do you feel that Python is a good first language for those who aspire to be career programmers? Even though I'm a proponent of dynamic typing, I feel like a lot of beginners end up struggling with questions that come from not understanding types and their implications.

spark magnet
#

i would say if it matters in a python program, you can learn about it in Python

raven ridge
#

I think every programmer should learn a statically typed language at some point, but I don't think there's any reason it should be their first language.

paper echo
#

Python isn't perfect as a beginner language, but others are all worse that I can think of, for some reason or other.

halcyon galleon
#

I do feel the road-bump that a lack of awareness around types can cause. But I don't think it's a large enough road-bump to matter long-term. When we're first learning, it's messy and clumsy. Quite often with no particular goal in mind yet.
Python's lack of static typing is, in my opinion, forgiving to that early stage of free-form development. It helps keeps interest for some longer than alternative languages.

spiral willow
#

so I understand those who are like, let's hook people on something that won't blow off their leg so they don't throw up their hands and quit

spark magnet
#

I don't understand why people think Python won't make you learn about types. Even without declarations, all values have a type, and the type matters.

spiral willow
spark magnet
spiral willow
spark magnet
spiral willow
#

mypy won't always catch everything and it's not a feature of language vs something like C# which will error out

#
PS C:\Users\rabbi> [int32]$a = 'Hello Nedbat'
Cannot convert value "Hello Nedbat" to type "System.Int32". Error: "Input string was not in a correct format."```
raven ridge
#

beginners' programs tend to be simple, and every line of the program is executed every time they run the program. There's not much of a difference between type errors happening at run time instead of at compile time for those users.

swift imp
#

I don't think C is a good first language

#

I don't even think C++ is

#

Maybe if the individual is bright in STEM

#

I think python lets an individual learn computer science concepts without being side lined by all the gotchas those languages have

#

Writing largish projects in C is fucking rough

molten fulcrum
#

hahahaha

#

try writing Assembly code 🀣 you will think C is a HIGH level launguage after using Assembly code

visual shadow
# spiral willow https://www.jetbrains.com/lp/python-developers-survey-2020/

This is exactly the wrong kind of audience for saying for what is good for beginners. I think developers who have made it through "the gauntlet" so to speak think it's a great idea to put beginners through it because they did so. It's the ultimate survivor bias at its finest. There's so many beginners who start with C or C++ and quit programming forever because they get frustrated at not really making much progress.

#

It's a real shame no one gets to hear their side of the story. I think your first language should be easy, and python is a great candidate for that. Learning python as a first language doesn't mean you'll be crippled forever, as if once you learn python you can't learn anything else? For what it's worth, I used to believe in the gauntlet once. Not anymore.

gleaming rover
#

IF the teaching process is good

#

I’ve taught it and I do really see

raven ridge
#

People learning Python as their first language certainly do get confused by types, but I don't think that's in any way unique to Python. Without some experience teaching a statically typed language to people as their first language, I'm not convinced that type errors emitted by the compiler would be any more understandable to the newbies than Python TypeError or AttributeError are

flat gazelle
#

the main merit of python as a first language is how incredibly easy it is to make cool things in it. You can get pygame and make a simple game much sooner than in C/java/C#, hell tkinter, for all its bad appearance is easy to use, allowing you to make simple GUIs. Javascript is even better there, so that is also a solid option for beginners

distant canopy
#

Anyone here learnt vba?

#

I have a problem which is when i was recording a macro , the first line of code in vba is always activecell.Offset

#

Can anyone tell me why

grave jolt
#

@distant canopy If you have a question unrelated to Python, you can ask in one of the off-topic channels

#

!ot

fallen slateBOT
ancient saddle
# visual shadow It's a real shame no one gets to hear their side of the story. I think your firs...

Definitely this. I took 2 C classes in college, with a terrible teacher to boot, as part of engineering and really ended up hating programming. About 10 years later I started looking around for something other than Excel for something I was doing and came across Python. Seeing incremental gains in skill on Python really gives you the confidence you need - for me, enough such that something I absolutely hated turned into something I really think about doing as a full time job.

halcyon trail
#

It really depends on the context, IMHO, for "first language"

potent hinge
#

IN NEW

#

πŸ˜„

halcyon trail
#

there's the first language of people in high school, who are 15. There's the first language for people who are at college perhaps studying psychology or something less technical. And then there's the first language for people who are say, undergrads in CS at MIT

#

A lot of the criticism regarding python as a first language that I've seen, and that I myself would level, is for groups like that last one.

potent hinge
halcyon trail
#

I don't think it's just about types per se, either. The MIT change made headlines not because they were switching from a statically typed language (they weren't), they were switching from Scheme. The advantage of lisps from a pedagogical point of view, when you're talking about trying to teach the fundamentals of CS to a very strong audience, are significant. I don't think python has almost any benefit in terms of a fundamental learning about CS aspect; the benefit of python is just that it's a nice language with a lot of libraries so maybe people can pull together a small, real project more easily (MIT has admitted as such). So I think this is the (justified) source of comments on "watering down"

#

So, I think you can't talk about "python as a first language" without first specifying "first language for who" (and whether it is really likely to be their first language, or just their first language in a particular setting, like college). Otherwise, it's likely that different people discussing just have different people in mind.

flat gazelle
#

yeah, python is great for younger people and self learners who need motivation beyond "I need to pass this course". If you have to bear with it, pretty much any language will do fine, and there are very good arguments for using things other than python.

halcyon trail
#

Agree, python is a fantastic choice for many people, I would have loved to have python as my very first language in high school, instead of VB or Java.
But I feel like I would have lost a lot if I'd used python instead of C++ for my algorithms and data structures course. I don't really understand how you can teach data structures without it being fuzzy, without using something like C or C++, tbh.

charred pilot
#

with dsa, there's always the feel that you're reinventing something, since python's builtin structures are so nice

flat gazelle
#

well, there are data structures the mathematical concept, and there are data structures the "how to arrange memory to be fast" concept

paper echo
#

@spiral willow that survey indicates to me that people are using Python in situations when they shouldn't be using Python, not that Python is bad for a newbie language.

halcyon trail
#

Memory layout, and the usage of pointers, are so incredibly intrinsic to data structures, if those things are not explicit in the language, then you need to constantly backtrack and say things like "well, in python since everything is a pointer, this is a linked list..." etc

flat gazelle
#

the former you can teach in anything, the latter you do want something in the category of C

halcyon trail
#

@flat gazelle no, something like an array vs a linked list, the "mathematical concept" is defined by memory layout

paper echo
flat gazelle
#

probably C, since some data structures are impossible in rust or modern C++.

halcyon trail
#

there are cases where the memory layout is a mere optimization on some mathematical algorithm, yes, but there are also cases where it's not so

paper echo
#

Knowing that a dict is a hash table and blah blah blah is intermediate, not beginner stuff

halcyon trail
#

@flat gazelle what data structure is impossible in Rust or modern C++? that's news to me.

charred pilot
#

i was under the impression that unsafe rust was basically C

halcyon trail
#

@paper echo it's not about beginner vs advanced in the sense you're thinking of it. And you're talking about software engienering, not computer science.

flat gazelle
#

double linked lists afaik do not work, since there are two owners of each node

#

now yes, you can use unsafe

halcyon trail
#

Data structures and algorithms, and learning about arrays vs linked lists vs BST's, is usually a very early course in CS programs

paper echo
halcyon trail
#

Then maybe there should be more programs that cater to that. But a CS program is still a CS program, and needs to educate people about CS.

#

80% of the courses offered in CS are largely irrelevant for SWE

flat gazelle
#

but yeah, teaching DSA in python is inevitably going to skip over some concepts

paper echo
#

That's fair. We need more serious SWE vocational programs, something more serious than a boot camp but less involved than a CS 4-year degree.

halcyon trail
#

Yeah. There are places where CS and software engineering are separate programs

#

E.g. University of Waterloo in Canada.

paper echo
#

I like that. Imagine conflating physics and mechanical engineering!

#

Or conflating biology with biomedical engineering with biostats with medicine...

halcyon trail
#

Well, biomedical engineering programs are extremely new

#

in the grand scheme of things

#

probably in the past most people doing biomedical engienering, were not people who studied biology in undergrad at all, but people who studied engineering and then filled in the biology later

paper echo
#

Interestingly, less new than SWE programs (as far as I know)

#

But I went to a school that had a very strong BME program, including an undergrad BS degree

halcyon trail
#

yes, it's definitely caught on more

#

Actualy, here's a pretty cool grpahic, i fyou're interested

#

So, this is where I did my undergrad, University of Toronto, it's a top 30 or so engineering program in the world, Engineering Science (which used to be called Engienering Physics) is their sort of "elite" program, the idea is that you're probably studying things that are going to lead to research as opposed to working on the current standard industry stuff

paper echo
#

Very interesting graphic, thanks

halcyon trail
#

the first 2 years are general, and then the last two you pick an "option", one of which when I went to school, was biomedical

#

can see how the options have evolved over time

#

biomedical starts in 1993, which makes sense to me

#

it's always tricky though I guess, just how much "rigor" to include in any given program. E.g. I mentioned the waterloo software engienering program but it's probably not at all what you were suggesting, it's waaaay more rigorous than that, you have to take a lot of electrical engineering for that.

#

I guess you want something where people learn at least basic CS reasonably (like, basic algorithms and datastructures, what a DAG is and some of the basics on that), but also a lot of applied software engineering stuff (version control, reproducbility, software design principles), and some programming languages

#

I don't actually know many programs that fit that bill

#

(or any, really)

paper echo
#

Yeah, that would be great IMO

#

And I think what be most directly beneficial to most people who want to get into programming as a career

halcyon trail
#

For many people, yes, I agree.

finite sparrow
#

i think you have a very CS centred view of things. the thing is though, that due to high level languages being a thing, a lot of programmers dont have to worry about large parts of CS. in fact, most of the concepts you mentioned i would have to look up, and i think im doing just fine writing python at my job.

not everyone needs to know CS, and thats okay. python is a language well suited for people that dont want to learn CS, and thats okay too.

halcyon trail
#

I agree python is well suited for those people, and that not everybody needs to know CS. I said pretty up front, that discussing python as a first language, you have to say "for who"

#

Without a doubt for people who have no plan to be professional software engineers or computer scientists, python is a great first language

austere moon
#

Programming languages are the tool, CS is the blueprint. Anyone can swing a hammer. An architect will know where to swing it and why you should use the hammer in the first place.

finite sparrow
#

an architect rarely swings a hammer.
anyone with a bit of common sense can tell when a hammer isn't supposed to be used.

austere moon
#

It's not an airtight analogy.

finite sparrow
#

not even remotely. thanks to high level languages, python being one, the CS knowledge is not really needed to create even large projects.

halcyon trail
#

I don't really agree. It's not about high level languages so much, it's more like, if other people have already solved the theoretically most difficult problems and offered the solutions to you as packages

#

dependency resolution for example is a major concern of all large problems, and it's an NP-complete (or NP hard?) problem

#

*all large projects

finite sparrow
#

the fact of the matter is that a lot of people can be effective developers with little CS knowledge

halcyon trail
#

similarly with git, because you don't have to solve version control on your own, your developers can get away with memorizing half a dozen git commands, and not worry about the mechanics of the underlying git DAGa nd hashes

austere moon
#

Levels of abstraction. You don't "need" computer science to do anything anymore.

finite sparrow
#

does that mean CS is pointless? of course not. but its simple not relevant to many.

halcyon trail
#

Yeah, but like anything, there are jobs that demand more, and jobs that demand less

#

in any particular category of knowledge

austere moon
#

But your efficacy as an engineer will be much better if you do have some cs knowledge (with or without a degree)

halcyon trail
#

At any rate that line of thinking that all that people need to know to be effective programmers is to know Django and basic git, or whatever, has already been heavily explored, the result is boot camps

#

and while boot camps aren't a total failure, most people I know don't think of them as an unqualified success either

finite sparrow
#

are bootcamps the only alternative to a CS degree?

halcyon trail
#

I think that's why salt was suggesting something more in between a CS degree and a boot camp, which isn't really available, and I agree with him that it would be very good for many people (and companies)

#

well, I'm sure alternatives exist, I can't claim to know everything that's available. Just talking about what exists at scale.

austere moon
#

It has to be one rager of a fire though. >_<

halcyon trail
#

sure, self education is an alternative, doesn't work for everyone though

#

Eh, I dunno, I don't have a CS degree

austere moon
#

I don't either. Just a large hot fire under the rump.

halcyon trail
#

i took a few CS courses

finite sparrow
#

interesting question: is there any application of CS needed when writing SQL?

austere moon
#

I have always had a passion though. I think that is the main difference for self-taught. If you don't have the passion, the only way to do it is with more formal education.

austere moon
halcyon trail
#

I don't do much with databases, but there are whole courses on databases at most CS programs. I guess it's like everything else, to do basic stuff you don't need a degree, for more advanced things, it will help

#

most people aren't doing advanced things

finite sparrow
sacred tinsel
#

wouldnt relational algebra fall under CS? you will be using some regardless of whether you're aware of it or no

finite sparrow
#

it depends on the exact dialect of SQL

halcyon trail
#

The thing is though that companies that can pay well generally still prefer people with degrees, if not in CS then at least in some technical field. There's value in signalling there, and beyond that I think it's not so much about whether or not a specific set of courses is valuable. It's more that you know that when there is a problem that does require more advanced knowledge, they're less likely to be put off acquiring the knowledge they need to.

austere moon
mild flax
#

i think CS extends a bit beyond turing-complete systems, despite the name

halcyon trail
#

why "despite the name" - CS doesn't imply turing complete even in name

austere moon
safe hedge
halcyon trail
#

turing-complete is just one category of computational machines, there are others both more powerful and less. Turing-complete is just the most popular.

austere moon
halcyon trail
#

@safe hedge indeed, I'm around that a lot, i was actually originally hired to be a person like that πŸ™‚ I was hired for my math skills, not my programming skills.

safe hedge
#

I think the reality is that it is often easier to bring a technical person up to a working level of programming than a CS person up to a working level of physics/maths/bio/whatever else

halcyon trail
#

Sure, even out of my very limited knowledge, you have things like quantum computers

#

they are more powerful than turing machines in some ways

mild flax
#

I was just talking about computation in the Church-Turing sense

safe hedge
#

Although my experience is the best teams have a balance of both

halcyon trail
#

since they can solve certain categories of problems faster

mild flax
#

usually the notion of "powerful" in terms of computational systems is the set of functions they can compute

halcyon trail
#

Well, the "working level" in the domain, is usually much higher than the "working level" in programming. THe code doesn't have to be beautiful, it just has to work. But if you're working in a domain, then the work in the domain needs to be top tier.

mild flax
#

and I don't think quantum machines can do more than classical, just some functions faster

halcyon trail
#

Okay, fair enough, I guess it depends on how you consider "power"

#

I was using it more in a practical sense than theoretical one

clever quail
#

i'm creating an application but i don't understand why this code doesn't work, a button should come out with hello kivy world
KV = """
Screen:

MDRectangleFlatButton:
   text: "Hello kivy world!"
   pos_hint: {"center_x": 0.5 "center_y": 0.5}

"""

magic python
#

these lines: https://github.com/dropbox/pyannotate/blob/master/example/example_conftest.py#L7-L15

Cause some of my tests to fail, specifically reading in a pandas dataframe, I don't really understand why this is happening though?

I've not got a MWE at the moment, but as Im not really that familiar with pytest and fixtures i thought perhaps there was an obvious reason why these lines would cause failure in other tests (tests which are writing / reading files specifically)

fallen slateBOT
#

example/example_conftest.py lines 7 to 15

def pytest_collection_finish(session):
    """Handle the pytest collection finish hook: configure pyannotate.

    Explicitly delay importing `​collect_types`​ until all tests have
    been collected.  This gives gevent a chance to monkey patch the
    world before importing pyannotate.
    """
    from pyannotate_runtime import collect_types
    collect_types.init_types_collection()```
grave jolt
#

With PEP 657, do you think it would be a good idea to encourage beginners to use 3.11 when it comes out?

#

!pep 657

fallen slateBOT
#
**PEP 657 - Include Fine Grained Error Locations in Tracebacks**
Status

Accepted

Python-Version

3.11

Created

08-May-2021

Type

Standards Track

charred pilot
#

i don't think so, this issue only really comes up in more complex code

#

i guess it depends on your definition of "beginner"

rich cradle
#

I personally think yes. With the better errors in both 3.10 and 3.11, it'll allow beginners to see where they're going wrong a bit easier, even without consulting someone.

mild flax
#

would there be a downside to them using 3.11?

visual shadow
#

Good question. Library support when it's new is the only thing I can think of.

#

And there's perhaps an argument for saying that beginners won't really be affected by it

#

I think this won't solve the problem of beginners choosing not to read error messages though, that will still stay same.

#

But yeah, that aside, good error messages? Easy +1

#

Looking at the pep, I'm getting rust* vibes with the ^^^^ style indicators. Is that something popular in other languages as well?

halcyon trail
#

I mean I think it's always beneficial to upgrade in python, the breaks in upgrades are pretty rare so library support isn't that likely to be a real issue, mostly (until that one time it is)

#

but there's usually work associated with upgrading, at most companies

flat gazelle
#

it always takes about a month for packages to catch up to python versions

gleaming rover
#

IIRC discord.py did not support 3.9 on launch? and people were asking why

gleaming rover
visual shadow
flat gazelle
#

yeah, things that need to rebuild themselves have a hard time

clever quail
#

lol

halcyon trail
#

that's a fair point I guess, the way that C works on Linux at least everything needs to be 100% consistent.

#

I guess that this could be mitigated if there was some, at least partial notion of ABI compatibility, probably a lot of the python projects with C components are using the same bits and pieces

flat gazelle
#

cpython afaik has a stable minimal ABI now, but not all things use it and some things can't use it, and so you have to rebuild for every version due to possible ABI changes

raven ridge
#

The things that can use it don't need to rebuild, but not everything can use the stable ABI (some important things, like the buffer protocol, aren't exposed through it) and some things choose not to use it (Cython notoriously pokes around at implementation details of CPython for the sake of performance)

halcyon trail
#

cython I can understand, it seems surprising for things like numpy though that they would need to be rebuilding all the time

static bluff
#

If I have a machine (class/object) that can be configured with arbitrary callbacks, running on a loop and executing some callback based on some condition each step

#

What is the best, I should say, most pure/pythonic way store state between iterations

#

The easiest way would be to attach state as attributes to the machine. One iteration, callback X sets state attribute Y, and then another iteration, callback Z checks state Y and uses that within its logic

#

But I've been advised that I should be storing state as local variables within thee function containing the loop. That kinda screws with the whole callback methodology in total tbh because it means pumping in, an returning, a large amount of information to these callbacks- which are functions/methods defined elsewhere

#

Additionally, as with callbacks, the state attributes the machine is a matter of configuration, with that configuration happening in another, largely unrelated step

halcyon trail
#

Is this the same code that we discussed?

static bluff
#

yeah

valid rose
#

shouldn't libraries made in 3.10 automatically be usable in 3.11? its not like 3.11 brought sone breaking changes right?

static bluff
#

I've made a bunch of changes and I'm pleased with it, but I'm still struggling wrapping my mind around- well- not only what you were saying about local variables/state but also just an effective way to handle it. An object, with state variables that are configured by a separate (non-trivial) other process, which persist across multiple iterations of a loop and must also be exported to, altered by, and returned from methods defined elsewhere

#

Sorry, mouthful. But I wanted to summarize my problem properly

halcyon trail
#

if you mean "pure" in the usual sense, then simply a generator is the purest solution

#

it's a one way flow of state

#

state that doesn'tneed to be messed with cannot be

#

then you wouldn't use callbacks, but just yield everything that needed to be, and process it in a for loop

#

as for the callbacks, basically what you seem to be saying is that my functions have too many arguments? They need as much state as they need. If you feel like there's too many arguments, you can always create a dataclass or something and pass it in that way

#

that's basically what you were doing before, the difference is that you basically had a bit of a (demi?) god class; the class carried all the state around, it was the customization point, it handled parsing, etc

deft pagoda
#

you can also store local state in a generator --- send callbacks into the generator to be executed on every step if you want

#

though i have no idea what you're building

static bluff
#

The way it stands now, callbacks need access to: the name of the input file as well as the full text of the source code, the start and end positions of the current token, any flags that might be in play, the matched literal and tokentype, and I think one other thing but I don't have the code right in front of me

halcyon trail
#

yeah, you can do that as well, though it's a bit more obscure at that point, practically speaking. However, in this case, something is being parsed, so sending data back in shouldn't be necessary

#

the obvious first question is, why do callbacks need the name of the input file, and the full source code text

static bluff
#

Throwing an error

halcyon trail
#

or the start and end positions of the current token

#

if that's the only reason they need it, then you're generating the error from the wrong place

#

have the function that's doing the tokenizing catch exceptions from the callbacks, and rethrow with that information

#

but this is a good example of why I simply prefer yielding everything to using callbacks, in python

#

if you yield things, then the top level would have access to that information as local variables, in the for loop, and you could just include it when you throw

#

either way though

static bluff
#

All of the 'decision making' about whether or not a matched token should or should not be generated is done by callbacks, defined outside the parser class. This is specifically so that I don't have to hand code that logic into the loop itself

halcyon trail
#

my preferred way would prob be something like this:

@dataclass
class TokenKindOne:
    ...

@dataclass
class TokenKindTwo:
    ...

filename = ...
with open(filename) as buffer:
    for index, token in tokenize(buffer):
        # replace with pattern matching in newer python
        if isinstance(token, TokenKindOne):
            ...
        if isinstance(token, TokenKindTwo):
            ...

etc

static bluff
#

By definition, if the logic is being performed elsewhere, than information about state- even as simple as where in the source document the parser is currently looking- must be piped to that function

halcyon trail
#

I don't really follow I'm afraid

static bluff
#

Also, and really I'm curious, what is the difference between attaching state directly to the parser, and attaching state to an arbitrary 'states' data class and piping that through, as you offhanded mentioned (offhandedly)

#

Its all just a namespace

halcyon trail
#

you said they only need it for throwing an error; the way you'd handle that with callbacks is something like:

def tokenize(buffer, callbacker):
    while ...:
        try:
            callbacker.callback1(....)
        except RuntimeError as e:
            throw RuntimeError(f"Exception originally thrown from callback1; in buffer {buffer}, index {index}")
#

etc

static bluff
#

The way I see it, if I have a machine whose purpose is to traverse input, making choices based on what it sees, in order to produce from that input- it seems totally logical that that machine's state be attached to the machine

halcyon trail
#

that way you don't need to pass the buffer into the callbacker

#

well, sorry πŸ™‚ I think we already went in detail over the issues with the design

static bluff
#

Just, I've been pondering your perspective since we last spoke and I just can't see what you were trying to communicate

halcyon trail
#

πŸ€·β€β™‚οΈ

static bluff
#

XD Trying to

halcyon trail
#

I mean, what's the difference between just shoving everything into one giant class, vs having a bunch of smaller ones that encapsulate smaller details?

#

seems pretty clear there's a difference, right?

#

I think if you read about the fragile base problem (did you?), the single responsibility principle, etc, then maybe it will help make it clear

static bluff
#

brain

#

🧠

#

Maybe if I explain where I'm coming from, I could get some discourse on refining my approach. When I was reimplementing the tokenize.py tokenizer, I found that it performed 5 main functions (excluding a bunch of string logic, which I handle in a different way)

#

It uses a single, massive expression broken into groups to recognize which literal, if any, is next (in the buffer, which is source[characterindex:]. Based which group(s) are matched, it produces token X, Y, or Z. I accomplish this by instead checking each individual pattern, generating the corresponding token

#

Sometimes, additional logic is needed. Whitespace, for example, may be omitted depending on a boolean sent into the .lex() method. This logic is coded in place as part of the loop in the tokenize.py lexer. I accomplish this by using a callback attached to the tokentype which checks the setting and if needed, returns a PREVENTDEFAULT flag

halcyon trail
#

You're kinda jumping straight into the weeds. But handling whether or not whitespace can be omitted via callback already sounds stramge

static bluff
#

The four processes are:

keeping track of parentheses via a stack, popping open parens on and then popping them back off when the mate is found, and issuing an error in the case of a mismatch.

Keeping track of the indentation level, issuing errors as needed

Keeping a look out for 'continued' newline, to override the default indentation behaviour

Performing a termination procedure when the end of the file is encountered

static bluff
halcyon trail
#

Pass it as an argument to the parser function?

static bluff
#

By using a 'plug-and-play' (or build-a-bear, as I prefer) type approach I can implement all of this behaviour without having to rewrite the whole parser each time. And while the argument can be made that its no huge amount of work to rewrite the loop for each type of parser, its no more work in the long run to build a parser that accepts behaviour on a configuration basis

static bluff
# halcyon trail Pass it as an argument to the parser function?

Sure. I add in a state. Now all parsers inheriting from the have a base vestigial state they may or may not use. And when I find myself in another, similar situation for the next parser, add another check to the loop

Eventually, my parser class that was supposed to be 'plug and play' is accepting a huge number of arguments and checking a huge number of states to juggle various concerns of all its descendants- to the point where its easier just to split them into separate classes

#

And I could, I could split them in separate classes

halcyon trail
#

I don't find it sharp... Honestly though, I think maybe you need to learn these things for yourself

static bluff
#

but each parser is doing nearly identical but slightly different logic. Seems logical to me to build a standardized system for assembling a parser easy

#

Anyway, I thought if I explained where I was coming from it might help

halcyon trail
#

It's accepting the same number of arguments, either way, not sure if you understand that

#

You seem to be getting a bit hung up on maybe the lengths of argument lists, or maybe not liking having a couple more classes, even if it better follows SRP

#

At this point I'd probably just tell you to go ahead with how you want to do it and learn

static bluff
#

πŸ˜›

#

So I digress

#

My original question, about storing the parser's states in a way that they can persist over multiple iterations of the loop and be piped to and back from callbacks- but still be 'local' within the loop

#

Dataclass? Or even just a dict?

halcyon trail
#

Well, I suggested how to do that with dataclasses above

raven ridge
static bluff
#

My point exactly

halcyon trail
#

Dataclasses give you the benefit of easily checking which kind it is with us instance,.which will eventually be much nicer with pattern matching

#

And of course trivially enforces a bunch of correctness

static bluff
#

True

#

Though in this case, because what the actual value of a state is is impossible know ahead of time, enforcing any kind of typing adds a whole new layer of complexity which even I'm not stubborn enough to implement

#

Its 39 degrees here XD Which is about ten degrees hotter than it normally gets even in the summer

#

I am baked, literally. My brain is souflette XD

halcyon trail
#

I don't really understand what you mean

#

The schemas of the dataclasses are the same as the signatures of the callbacks, basically

static bluff
#

It is entirely too hot here in the west coast

#

I'm a tidbit north myself, I can only imagine how california is down right now

signal tide
#

is it possible to customize the (re)allocation size of containers?

vestal ibex
#

Is it possible to create a discord bot that can get in without admin permit?

finite sparrow
#

this channel is for discussion of advanced python topics in a more general sense. please claim help channels or ask in the appropriate topical channels
@undone oyster topical channel: #web-development
@vestal ibex topical channel: #discord-bots

charred pilot
finite sparrow
#

if its a very dumb or awful idea you might be able to get vco to add it to yeethon

signal tide
visual shadow
#

No. That is baked into Cpython

#

Why do you want to customize this?

signal tide
#

No reason I was just curious + thinking about the growth patterns used

#

The closest thing I can think of would be a queue but that’s more modifying + locking the size of the container rather than the mem

visual shadow
#

Ah. Well if you wanted you could "pretend" arrays are lists, and try to implement the o(1) append using arrays as a fun exercise.

#

Might get you the benefits of seeing the growth for yourself without the downsides of having to butcher python for it

fallen slateBOT
#

Objects/listobject.c line 67

* The growth pattern is:  0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ...```
signal tide
#

True, I think for the most part I understand it pretty well (altho my c is hella rusty so I could be misinterpreting something), my thought process was if I have 65 (obviously wouldn't matter at this scale but I cba to do the math) objects, the container would have to allocate an extra 12 buffers (?) to compensate for the 1 extra

halcyon trail
#

yeah

#

when you append to a list of size 64, its memory is already full (assuming it's been growing by repeated appends)

#

so it allocates a new chunk of memory with room for 76 objects, copies the first 64 objects into the new memory, and then appends the new one

#

so when you hit 65, it allocates 76, deallocates 64

signal tide
halcyon trail
#

what's the issue that you want to work around?

signal tide
#

it's not an issue I have, just a theoretical, but to be able to say allocate 65/68 slots instead of 76

peak spoke
#

Not that the memory that consumes should be an issue, but how are your list created? It won't preallocate when it knows the length

halcyon trail
#

that's what I was wondering, whether python sticks with the growth patterns when it's creating a specific size list

#

i've seen implementations of some things that do, and those that don't

#

FWIW, python isn't really about offering that level of fine grained control

#

and it doesn't offer much benefit in a language like python either

#

in say, C++, the list equivalent, std::vector, lets you control its capacity more directly

#

(and view the current capacity, as distinct from size)

peak spoke
#
In [60]: sys.getsizeof(list(range(65)))
Out[60]: 576

In [61]: sys.getsizeof(list(iter(range(65))))
Out[61]: 600

In [62]: sys.getsizeof([i for i in range(65)])
Out[62]: 664
halcyon trail
#

hmm why are there 3 different answers, that makes no sense πŸ™‚

peak spoke
#

I'm not really sure on the iter but it's probably because it can't get its length but is still static and can be done in one step unlike the append which list comps use

halcyon trail
#

list comprehensions using append when the iterable is of a known size and there's no filtering is pretty inefficient

#

quite surprising, that's as low of low hanging fruit as you can get

peak spoke
#

!e

import dis
dis.dis(compile("[i for i in iterable]", "", "eval").co_consts[0])

list comps are fairly simple, I think they just accept the value you're going over as an arg and handle everything in the same way

fallen slateBOT
#

@peak spoke :white_check_mark: Your eval job has completed with return code 0.

001 |   1           0 BUILD_LIST               0
002 |               2 LOAD_FAST                0 (.0)
003 |         >>    4 FOR_ITER                 8 (to 14)
004 |               6 STORE_FAST               1 (i)
005 |               8 LOAD_FAST                1 (i)
006 |              10 LIST_APPEND              2
007 |              12 JUMP_ABSOLUTE            4
008 |         >>   14 RETURN_VALUE
spice pecan
#

I assume that's because listcomps actually evaluate an expression and don't just unpack an iterable, it's just that in this case the expression is left unchanged

halcyon trail
#

even if they're evaluating an expression, if the iterable is one of known size and there's no filtering, you automatically know the size of the final list

spice pecan
#

That's fair

#

I wonder if unpacking gives a different result

halcyon trail
#

they're doing quite a lot of extra work, not only many allocations instead of one, but also many memcpy's

spice pecan
#

!e ```py
import sys
print(sys.getsizeof([*range(65)]))

fallen slateBOT
#

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

600
spice pecan
#

Same as iter, to be expected I guess?

halcyon trail
#

i don't have much expectations right now given that I can't explain why there are 3 different sizes yes

#

8yet

#

*yet

signal tide
halcyon trail
#

it's just strange IMHO because this is such an easy optimization to do, during bytecode emission, and it's used a great deal, it seems like it would be worthwhile

spice pecan
#

Perhaps the list constructor uses extend under the hood, which could have some additional optimizations over a series of appends

#

I could also be wrong

#

star-unpacking definitely uses extend under the hood, so my current explanation for the 3 results is:

  1. Passing an iterable with known length to the list constructor pre-allocates the memory, best case scenario
  2. Calling iter on the iterable drops the length info, so the constructor goes for an extend call instead (same for unpacking, which also uses extend)
  3. A listcomp does a series of appends over an extend, and doesn't pre-allocate even when no filtering or nested loops are involved and the size is known, which (for some reason?) performs worse in terms of memory
#

Interesting, extend seems to just call append repeatedly

raven ridge
#

Names are looked up dynamically, at compile time there's no way to know what range is.

halcyon trail
#

fair point

#

didn't consider that

#

this language is crazy πŸ™‚

raven ridge
#

I shouldn't say "no way", I guess, but it's not as simple as you imagined.

halcyon trail
#

I think no way to guarantee it, the best you can do is to have a branch to check if the range is the "standard" range

#

and then optimize that branch

raven ridge
#

Right.

halcyon trail
#

it's kind of a crazy state of affairs, making a language that dynamic. It has its uses for REPL applications but outside of that I think the benefits of being that dynamic definitely are not worth the costs

spice pecan
#

Technically, you could check for comps that return the same expression without altering it, and then replace them with an extend/iter call (depending on what kind of comp it is), but then I'd much rather show a SyntaxWarning of sorts, tbh

halcyon trail
#

Outside the REPL, you're basically throwing a huge amount of optimizations in the toilet, in exchange for the ability to monkey patch, or mock test, badly written code. I can't even remember the last time I replaced something at global scope like that.

visual shadow
#

Well, there are implementations that get rid of some of that stuff if you're interested in that

#

Pyston comes to mind.

halcyon trail
#

I don't think that pyston can do that optimization, since it claims to be fully compatible with python

#

the best you can do, as mentioned, is have a branch to check if range is the range, and then optimize in that branch

spice pecan
#

What I can't explain is why a series of appends allocates more memory than an extend, which just calls append until the iterable is exhausted

halcyon trail
#

well, extend doesn't have to be implemented exactly that way

#

if I were implementing extend, I'd first to do an isinstance check for a sequence-like type

#

i.e. something with a known size

spice pecan
#

Feeding it an iterable without size info still provides the same results

halcyon trail
#

interesting

#

who knows

spice pecan
#

And the source code does just call append

halcyon trail
#

kind of funny to provide that function then

spice pecan
#

Unless range_iterator provides a length hint, actually

#

Oh, it does

halcyon trail
#

πŸ™‚

spice pecan
#

That explains it, nevermind

#

It doesn't give len, but does give __length_hint__, and extend checks against that

halcyon trail
#

makes sense

#

length hint doesn't need to be as precise as len

#

as the name implies, even a hint can be useful

spice pecan
#

Yeah, it makes sense, and since range can give you the exact length as the hint, extend works the same on both range and its iterator

#

It probably falls apart if wrapped into a gencomp

halcyon trail
#

yeah, i was thinking that

#

but I still don't see how we have 3 different cases

#

there should still be either known size, unknown size, that's it

spice pecan
#
  1. Create new list with known length, allocate exactly that, no pre-allocation
  2. Create new list, extend with known hint and a single overallocation
  3. Create new list, append repeatedly with overallocations
#

Actually, let me check the constructor

#

Yeah, extend does resize, which provides overallocation, and the constructor for known-length iterables seems to use preallocate_exact instead

#

You could shove a check for an empty list into extend I guess, that would be a slight optimization

halcyon trail
#

that doesn't really clarify to me though what's going on

#

extend with hint can still only really do two things, you would expect

#

grow to the exact size of the hint, or grow to the first entry in the size progression larger than the hint

#

I guess there is a third option, which I guess is wha thappens

#

use the hint as the "just filled" size and calculate the over allocation using it as a basis

spice pecan
#

The difference is the hint route calls "list_resize" which, depending on the current capacity, either doesn't reallocate at all, or allocates enough to fit the specified length + overallocation

#

While the constructor calls "list_preallocate_exact", which just gives you that length with no overalloc room

#

extending usually implies you're actively resizing the list, so additional room would be needed to amortize for future appends, while prealloc is only used when creating new lists, which might or might not have new appends later

#

At least that's how it seems to me

halcyon trail
#

yeah, what you're saying makes sense

#

over-allocating in any case isn't a big deal. the real question is whether the initial capacity gets set correctly

#

that saves you a bunch of reallocations and memcpy's and it's fairly substantial

spice pecan
#

That is true

halcyon trail
#

especially since the python growth factor is only 9/8

#

what's 1 + 8/9 + (8/9)^2 + ...

#

it's 9

#

so, that means that when you use append repeatedly to get to size N, you've done 9N worth of memcopying

#

quite a bit

#

compare to the 2x growth factor that people often use, where you only do 2N worth of copying. Or, a 3/2 growth factor, where you do 3N worth of copying.

#

sorry I guess I shouldn't include the leading 1

#

It's actually 8N vs N vs 2N

spice pecan
#

Mhm, that's quite a lot, and I'm glad length-hints and sequence checks are there to soften that

grave jolt
#

It's a bit strange that map doesn't get a length hint if the iterator from the iterable it wraps has one

halcyon trail
#

just another way of Guido telling you not to use map πŸ˜›

spice pecan
#

It is inconvenient, yeah

#

It'd be nice to have the ability to return NotImplemented or None to indicate that there is no length-hint

grave jolt
#

dirty hacks

#

Those precious 64 bytes!

spice pecan
#

What if there's no length?

grave jolt
#

also, it doesn't handle the case with multiple iterables

spice pecan
#

Unfortunate

grave jolt
#

the ultimate hack

red comet
#

[EXPERT OPINION NEEDED] I have a big project in which I will create [OUTPUT] pdf file (report file) from [INPUT] excel data (either file or make our own in python), plots (matplotlib), word data (either file or make our own config data) or any other config [editing, customizing] data will be available using GUI for our client... Which I will maintain as well later.. Please someone guide me about right tool or right path.. Actually I know Python as Intermediate, know tkinter as well (but old fashioned and client will not like) and I want to achieve this goal in python. I am confused with Kivy, Tkinter or any other GUI based library or framework... I also thought about flask or django (know basics of these) and think that It may have capability to convert to some GUI (cool or fancy).. Other options are also welcome with easy path.. Other programming language can be applied but will take time for me to learn. Thanks

paper echo
#

@red comet if you are asking about gui frameworks, i recommend asking in #user-interfaces . otherwise maybe you want to ask in #software-architecture about how to structure an application like this. #internals-and-peps is for discussion of the python language itself, e.g. its syntax and its internals

red comet
grizzled karma
wheat ginkgo
#

I was gonna make a proxy with a raspberry pi so I can go on blocked sites at school, is that a good idea?

#

I know it's do-able

faint quail
#

probably against school policy Β―_(ツ)_/Β―

unkempt rock
#

Is it possible to run two sql.inserts back to back

#

So it's impossible cool thanks

charred wagon
#

No one said that. Don't make assumptions based on silence. If you have database questions, head over to #databases

tidal marten
#

Hello, guys. I noticed that there is no mention of how operator precedence and associativity are handled in Guido's write up about the new PEG parser. Are those not handled in the parsing stage?

prime estuary
tidal marten
#

So I guess the recursions are limited such that you won't have to worry about precedence and associativity?

#

That's pretty neat

magic python
#

i guess the grammar πŸ€”

jovial flame
magic python
visual shadow
#

I believe it's personal preference.

#

One general convention that does seem to happen almost subconsciously is that functions should be "actions"

magic python
visual shadow
#

I think there's some conventions in other languages, where stuff like <noun>_<verb> is common. I've however seen a healthy mix with this flipped as well, and both seem to be just as fine for readability.

#

So stuff like file_read() and read_file() seem interchangeable to me. Fwiw I personally tend to write verb first, but I'm ambivalent to it

magic python
visual shadow
#

Think of it in terms of how the calling statement would look, not the definition.

#

So would you rather have countries = get_valid_countries(foo, bar) or countries = valid_countries(foo, bar)? To me, I prefer the former

#

When I read a name that has a verb, I'm ready to expect a function. When I read a name that doesn't have a verb, the brackets make me pause and reevaluate, because valid_countries seems like some data to me by itself, not a function.

#

So I don't think the get is redundant.

#

(but this is just my opinion. Not sure if there's a convention for this)

livid dove
#

i usually try to make the name as descriptive as possible without adding unnecessary details

#

also idk how i'd describe it but i add the filename to the name as well so for example in a logging module i dont name the function setup_logging but rather just setup

static bluff
#

I'd like you guys' input on building a very simple type enforcement system (via decorator, I'd assume)

#

I'm building an API for use in building applications and games. As such, I'm not the end user and I can't trust that my end user is reading the docs or using any kind of linter

#

I'd prefer that users of my program see an unambiguous 'could not execute <function>, arg <whatever> must be of type <type>' style error. The alternative is: a) I manually assert types coming in b) whatever error the bad input results in bubbles to the top and the user wades through the stack/internals to deduce what the problem is themselves

#

I'm open to discussing the purity of type assertion in this context. Beyond that, what would be the best approach implementation wise to automatically asserting types via decorator

halcyon trail
#

what exactly do you mean by best approach? I think you pretty well summed it up, you'd want to use a decorator

#

beyond that, you'd create a new function that reads the annotations, does isinstance checks, if any fail, throw, and then call the original function

#

just keep in mind that when you try to "combine" python's static and dynamic type system, there's a lot of edge cases

#

An obvious example being generics; it's not really reasonable to iterate over x: List[int] and verify that every element of x is really an int

static bluff
deft pagoda
#

there's a beazley talk where he implements this exact thing --- he calls them contracts

static bluff
#

The only reason I'm not doing it by hand is that I'm expecting a few hundred arguments will need to be checked, so it might be faster to automate than assert by hand

deft pagoda
static bluff
halcyon trail
#

You may want to have a global flag that controls whether the decorator actually does the checking

#

or I guess just have the decorator use assert instead of raise, since there is a global way to disable asserts

#

Beazley's characterization of this as a contract precondition makes sense, and assert is how you enforce such things

wheat ginkgo
halcyon trail
#

It's just atypical in python to actually have a narrow contract

unkempt rock
#

question: so can you run programs from ur idle ex(pycharm) in an idle shell?

tidal marten
#

What difference does left recursive vs non recursive make?

# not left recursive
disjunction:
    | conjunction ('or' conjunction )+ 
    | conjunction
# left recursive
sum:
    | sum '+' term 
    | sum '-' term 
    | term
quasi hound
#

@static bluff you're the guy making a custom python implementation right

#

with actual type definitions and stuff?

#

ok good you are

#

i got a good idea for you

#

change modules to the way C++ has them

#

where you only export certain functions and vars and shit

#

so you don't have to add _ at the start of each "private" method/class

#

and just make them actually private

#

assuming you're also adding private instance methods/vars which you are iirc

#

also you're doing it in C right

static bluff
#

Still though, all public facing functions need to would have their arguments validated

quasi hound
#

Nice

rich cradle
hexed maple
#

Or you can always make you own it's not that hard

magic python
#
def f(p : str):
    p = pathlib.Path(p)

it seems that mypy will complain about this, as there's Incompatible types in assignment (expression has type "Path", variable has type "str"), but this seems like a pretty common thing to do, what's the recommended approach?

halcyon trail
#

create a new variable name

#

def f(ps: str): p = pathlib.Path(ps)

#

another option, not sure if mypy is clever enough for this or not, but given you're converting to a path anyway it would probably make sense to accept a path as well as a str

#

so you could do

def f(p : Union[str, Path]):
    if isinstance(p, str):
        p = Path(p)
#

the question is whether mypy is clever enough to understand that p's type is exactly Path going forward in that function

peak spoke
#

It should be

quasi hound
#

I doubt it

peak spoke
halcyon trail
#

indeed, looks like it is

magic python
halcyon trail
#

you want to avoid creating a new variable name?

magic python
#

yes

halcyon trail
#

why?

#

maybe union is the right choice, maybe not, but it shouldn't be on the basis of not wanting to create a new variable name

magic python
#

because sometimes there are situations where something along the lines of :

a = ... 
a = ... 
a = ...

is done, and it's not much sense to make a new name for each step

#

seeing as we don't have pipes or whatever i guess

halcyon trail
#

it's a pretty trivial thing, and you can always factor out a function

magic python
#

what's trivial?

halcyon trail
#

in most cases, different types carry different content, path/str happens to be a case where you have two types that carry identical content (when you want to regard the string as a path), and strings are over-used as paths for historical reasons

#

it's trivial to give them different names

peak spoke
#

most probably will help you prevent mistakes too

magic python
#

it's pointless and doesn't help readability in the case of several steps

halcyon trail
#

it doesn't really hurt it either

magic python
#

it does - this is a pointless convo tho

halcyon trail
#

that's true. but honestly, every time you ask for help with static type annotations, it feels fairly pointless - you ask for help, and everything that people tell you is a good idea wrt type annotations in python, you explain why it's bad

#

they're optional, so maybe just, opt out?

magic python
#

probably gone too far now lol - these kind of patterns are very common when applying several operations to something though, and renaming the var at each step would often be kinda pointless.

#

there are some things which have been annoying which i think long term might be useful though, like being more careful to use a single datatype in a list - never really thought / cared about that before, but maybe it's a better idea in general πŸ€”

halcyon trail
#

probably, or at least, that's realistically the consensus in industry (or if you prefer, the direction in which consensus is moving)

magic python
#

i wish things like monkeytype were better as it'd save me a bunch of time

#

i guess monkeytype wishes my tests were better tho

#

i need to A/B monkeytype with pyannotate, i think the latter worked a bit better, but needed some fixtures put into the conftest file or something

halcyon trail
#

you can try this flag

#

if you really like this style

#

I think it will allow you to keep reassigning to the same variable

#

with different types

magic python
#

i'm trying to get part of the project to pass with --strict atm... but idk if that's asking a bit much, i'll have a look at that flag tho πŸ‘

static bluff
#

Anyone working on anything fascinating?

jovial flame
#

How often do people use logging in their scripts / projects? I started to use it to help debug and troubleshoot and now I use it for almost every script

quasi hound
#

the logging module?

#

or what

#

i used logging once for a discord bot

#

but it got annoying

jovial flame
#

Yeah the logging module, it helps me with avoiding print statements to track what was happening behind the scenes

halcyon galleon
#

Logging is one of those things that I'm always happy to see in an application, always wishing it showed a little bit more, and usually wishing it wasn't as verbose. darkoLUL

#

Difficult to "get right" but worth the effort. Saves so much work when you need it.

copper tree
#

Hi, I'm a long time python user and recently wanted to take 4 apps (that share lots of code) and move them into a Monorepo.

The structure would be something like this:

my-monorepo/projects/app1
my-monorepo/projects/app2
my-monorepo/projects/app3
my-monorepo/projects/app4

my-monorepo/libs/shared-library1
my-monorepo/libs/shared-library2
In this example, each of the projects would one or both of the shared libraries. Lastly, they're all independent micro-services with their own Dockerfile(s).

Requirements:

  1. Imports resolve correctly
  2. Can Dockerize (docker composable for local testing would be nice!)
  3. Simple CI/CD to get into GCP Container Registry / Cloud Run

So far, I've looked into Bazel, Pants, Please, and Poetry but they all either have too little documentation, or seem to fall short on one/more of the requirements. Am I crazy? Is there a way to do this?

Is there a clean way to structure such a repo? Which technologies would help achieve this goal?

tidal marten
#

Is this a case of normalisation, where you should have two non-terminals?

brave badger
#

tl;dr each app and library lives as their own poetry project, and that any dependency to a library from an app is specified using a relative path

static bluff
#

Hey @brave badger , your name suggests you might be the right person to ask this

#

Why would a person choose functional programming over OOP?

brave badger
#

FP offers different approaches to abstractions and have some sensible degree of null-safety, not to mention powerful type systems in some languages

static bluff
#

So its just the tool for the job in some cases,

brave badger
#

As is for most approaches to software development

static bluff
#

Lots of cases, I assume

#

Now, and I know its hard to see one's own predispositions as predispositions; could if be simply a matter of taste that you prefer FP over OOP?

#

Is FP 'better' than OOP?

eager trail
#

I kinda wish there was a 6th level, between info and debug... like a less severe debug

torpid plinth
#

hey guys, what would be prerequisites for emulating a CPU in cpp. apart from cpp, what would be some of the prerequisites you would recommend for a newbie.

eager trail
torpid plinth
visual shadow
fallen slateBOT
terse orchid
#

x-12 = y-12+7 with this kind of linear equations, how can I convert it to ax + by = c form and get a, b and c?

I have heard of sympy but it's too complex (and too cool) that I couldn't find where should I look.

undone hare
#

Could you open an help channel and we talk about it in more details? πŸ˜„

terse orchid
undone hare
#

Sure, I'd curious to see

terse orchid
# undone hare Sure, I'd curious to see
from sympy import symbols, simplify, oo
from sympy.solvers.solveset import linear_coeffs
from functools import reduce

# t = 'x-12 = y-12+7'
t = 'x+21=2*(y+21)'

x, y = symbols('x y')

solved_eqs = []

for eq in t.split('='):
    simp = simplify(eq, ratio=oo)
    solved_eqs.append(linear_coeffs(simp, x, y))
    
print(solved_eqs)
reduce(np.subtract, solved_eqs)

I did it like this. One bad thing is it won't work without * in 'x+21=2*(y+21)'

undone hare
#

That's cool, I never really messed around with sympy too much

terse orchid
terse orchid
fresh plover
#

hahaha im also doing a math solver

#

with AI though

#

i had a problem with string splitting somehow can i get a sanity check?

#

how do i do a code block

terse orchid
#

By enclosing text with triple back quotes

fresh plover
#

(basic example)

#

and then the AI would understand that it needs to use those code blocks with certain coordinates or equations

#

and if it learns to combo the functions in the correct order

#

full automation

#

firstCords = "A(10,5)"
secondCords = "B(1,2)"

firstCords = re.sub("\)|\(|\,", " ", firstCords)
firstCords.split(" ")
secondCords = re.sub("\)|\(|\,", " ", secondCords)

print(firstCords, secondCords)```
#

: 0

#

yes so im trying to handle the input

#

why doesn't .split() work exactly?

#

for example firstCords[0] should be A firstCords[1] = 10 firstCords[2] = 5

#

welp got it anyways

terse orchid
naive adder
#

will b fun making bython (python running directly bytecode)

charred pilot
#

doesn't cpython do that

magic python
#

are there any sort of conventions around typing (typehinting) wrt having something as simple as possible? I appreciate that simple strictures are easier to type, but if there's something such as

def f(x : pd.Index) -> int:
    return sum(x)

this would work if x was passed f( x = list(pd.Index)), this makes the function a little clunkier to use (user has to convert to list), but maybe simpler / better overall? I don't have much intuition

charred pilot
#

imo that would lead to a lot of confusion, they should reflect what type you actually want

spark magnet