#internals-and-peps
1 messages ยท Page 135 of 1
the main annoyance here to me is that you can't construct handlers, directly passing format, and level
but again, i have my own format that I like to use, codebase wide, so I end up with small helper functions for logging that add handlers using my format anyway, and things like that
so it makes very little difference in the end
Maybe a third-party package will be a good way to explore this design space somewhat anyway
I ended up adding both yaml and toml support to the configuration.
yeah, maybe, it just faces the issue that IMHO it doesn't solve a big enough problem for people to want to use it. Using a package to save a dozen lines of very simple code, is eh
I feel that way even about loguru though
I kinda wanna stop coding after writing what I wrote last night screams
Pre-commit hook which automatically generates example configuration files if I edit my configuration and its defaults
....To an .env file, a json file, a yaml file, and a toml file
Hmmmm, logging conversation 
pathlib and os.Path have entered the chat.
that's actually an interesting idea. i'd personally do it with a makefile
oh, os.path.
eh. Pathlib is an entirely new interface
i'm more bothered by things like template strings (wtf why are these in the stdlib??), dictconfig and fileconfig, etc.
my burning desire to write from datetime import datetime as DateTime
template strings exist so that you can safely pass arbitrary objects into user defined templates
I did these for...... oh no. I just realised my configuration system is far from done
well, I made them so the end user would have a default base to build off of
i know why it exists, i just question why it's in the stdlib
i was also being somewhat rhetorical though. they used to add all kinds of random stuff in the name of practicality / availability back when it was really difficult/annoying to install python packages
what are template strings?
and now they're being very (justifiably) cautious about adding new things
i still scratch my head at how pattern matching got accepted
seems like hopping on the "we are typed now" trend
except in 1% of string formatting use cases
i wouldn't say it's useless, if i needed user-defined templates in an application i'd at least consider template strings instead of {}-formatting
here, if you want to see the pre-commit hook I wrote which exports to the four necessary files. https://github.com/discord-modmail/modmail/blob/cf906c007043c87ee70ee85beb00d099ced7cc0e/scripts/export_new_config_to_default_config.py
cool, ty
pattern matching IMO makes sense. Sure it's kind of insane in terms of spec, but argument normalisation was far more error prone and hard to grasp without it
which is something you do for a lot of public API functions
but how often are you pattern matching on types or protocols and destructuring individual attributes thereof?
I now need to make the user interface which can modify a configuration option while online-- this is legit gonna be the hardest part, wish me luck
overall, I do think extending the stdlib and language features is more of a good thing than a bad one
seriously please wish me luck
in my experience, it's more like this:
if isinstance(x, Thing1):
x_clean = process_thing1(x)
elif isinstance(x, Thing2):
x_clean = process_thing2(x)
else:
x_clean = x
so sure,
match x:
case Thing1():
x_clean = process_thing1(x)
case Thing2():
x_clean = process_thing2(x)
case _: # argh why isn't this "else:"
x_clean = x
well, with patma you could have an api that would run the process thing when matched, though I am not sure if that is intended
what are template strings?
case _: # argh why isn't this "else:"
Mostly because _ is a pattern just like the others and can be embedded within other patterns, such as case Thing2(attribute=_). That's difficult to do if it were an else: (although you could have both _ and else obviously).
https://docs.python.org/3/library/string.html#template-strings the first (?) attempt to clean up %-formatting in the stdlib, never really caught on
yeah, my issue is not with the existence of _, but with 1) not having else:, and 2) changing its semantics to discard the matched value instead of assigning to the name _
i know the main argument against else was "how far do you indent it?"
I am still in support of object() as the wildcard match
huh, I'll probably use template strings for this
does that not work @flat gazelle ?
syntax seems easier for an end user to put it TBH
it does, but it should've been the official way
eg "Hey, welcome to $server!" vs "Hey, welcome to {server}!"
right, it has its purpose i think
actually, which of those seem easier? 
if you were an end user (who didn't know much python)
I'll have to use pattern matching more in python to get a feel for it.
it does seem like a fair bit of complexity, and in the end most of the examples I've seen, it's basically just nicer if statements
Would you make it a special caseโas in, would you just turn that into a "don't process anything, don't bind names, just always match" special token?
In static languages it makes a lot more sense because it generally gets combined with smart casting
@wide shuttlethat's what it already does is the thing
@white nexus the $ doesn't clash with .format or % which is valuable, i think (the string needs to be specifically compiled before templating) and you can exercise greater control over the templating style
you probably don't want end-users to have control over float precision or space-padding
it is consistent in how it works in other cases, and object as the universal base type is well known, can be used multiple times in the same pattern without a new keyword
so whatever they configure it as is what is shown.
you can't split case over multiple lines too, right?
@wide shuttle Have you always been owner? If not, congrats! If so, don't mind me...
match x:
case (
Thing()
if foo(x)
):
you can't do this, right?
seems like string.Template is a bit of a wrapper over re.escape
possibly is, i have no idea about the internals
!d string.Template
class string.Template(template)```
The constructor takes a single argument which is the template string.
Helpful documentation
it just looks like re.escape is used to process the "delimiter"
it looks like it builds a regex for the placeholders and uses re.sub at templating run-time
oh god no this configuration is gonna be a mess
just realised that I need to have a validator for every string input
WELL.
TBH str.format may work as well
what are some advantagese of the one syntax over the other?
again i think the advantage of Template is more control for you, less control for the user
and depending on your application { might be more annoying than $ to have to escape
somewhat annoyingly there's no option to change the brace style, you have to override Template.pattern for that, which requires copying their somewhat ugly regex from the source code
I used it to do replaces where braces are valid syntax from the user, wouldn't want expose the escaping needed to be done in python to them. There's also the safe replace or what's it called
Gotta sanitize your inputs
also annoyingly you can't easily drop in a regex instance instead of re because of how Template.__init_subclass_ is designed
yes, but you have to override a lot of stuff to use pattern types other than the stdlib
so I stopped
is it? afaik it's a superset of re
the main reason i use it is for unicode character classes
yeah
which re doesn't support
Just double brain capacity and processing power, ez
one sec
I also have a questino
absolutely hell fucking no to that syntax
We've had some great conversations in this channel about None propagation (setting up your projects to return None in certain cases, perhaps with invalid inputs/data or when analytics have a low level of confidence). I've been thinking, how would that look like in practice? IMO it would be handled at the decorator level and be one of two things:
- Check to see if the input is None. If that's the case, return None
or
- Try except and catch errors related to None and then return None.
or
- Both at once!
Which might be preferable?
Sorry for text wall
modmail/addons/converters.py lines 17 to 28
LOCAL_REGEX: re.Pattern = re.compile(r"^\@local (?P<addon>[^@\s]+)$")
ZIP_REGEX: re.Pattern = re.compile(
r"^(?:https?:\/\/)?(?P<url>(?P<domain>.*\..+?)\/(?P<path>.*\.zip)) (?P<addon>[^@\s]+)$"
)
REPO_REGEX: re.Pattern = re.compile(
r"^(?:(?:https?:\/\/)?(?P<githost>github|gitlab)(?:\.com\/| )?)?"
# github allows usernames from 1 to 39 characters, and projects of 1 to 100 characters
# gitlab allows 255 characters in the username, and 255 max in a project path
# see https://gitlab.com/gitlab-org/gitlab/-/issues/197976 for more details
r"(?P<user>[a-zA-Z0-9][a-zA-Z0-9\-]{0,254})\/(?P<repo>[\w\-\.]{1,100}) "
r"(?P<addon>[^@]+[^\s@])(?: \@(?P<reflike>[\w\.\-\S]*))?"
)```
@unkempt rock i'd want something like this
defmacro foo(expr1, expr2):
...
where the arguments are all ast objects
Yes, I had to switch feature branches to send this ๐
no joke i would consider quitting python if that pep got accepted
That's hardcore
standards track? jesus fuck
Last year, Guido used the code name "Python 3000" to refer to a mythical future version that would be perfect but not necessarily backward-compatible. Since then, the Python team has realized that a quantum leap is not necessary. All desired changes can be implemented gradually using the new warnings framework and the future module to give users a transition period (see "What's New in Python 2.1" for more information).
from the linked article, https://www.linuxjournal.com/article/4731
I am not sure why but those regexes make me sad
noooooooooo
Doesn't matter as long as they work, though
i spent too long on them for anyone to be disappointed by me 
@unkempt rock am i reading this right? is this a compiler directive encoded as a comment?
# (func, _ast.STMT_MACRO, VERSION, ())
stmt_macro!:
multi_statement_body
or is this just an example of how a statement macro might look when it's being used?
hold on, no. i think i misread this
That's how I feel about my life and my parents ๐ฆ
@macros.macro_processor(macros.STMT_MACRO, 1_08)
def switch(astnode):
...
this is fine
no idea what 1_08 means but whatever
Just 108
yeah, it's a version number
interesting
i'm still confused about this pep, how do you actually define a macro?
the reason i suggested something like defmacro is because the parser should be able to pick out the defmacro's, apply them to the rest of the file, and keep going
this syntax
๐คฎ
do_nothing_marker!:
def foo(...):
...
this will completely fuck people up
since the current rule is the line below a line that ends with : must be indented
except if the line above ends with !:, then its okay
yeah, that's bad too
Hmm, it allows Python to scream at you.
try_!:
body
finally!:
closing
@white nexus maybe the idea is that you can use it to implement decorator-like things? i am really not a fan though
i have lodged my complaint https://discuss.python.org/t/pep-638-syntactic-macros/5352 but i'm sure this is just yelling into the void
Wdym scream
I'm mostly! not! used! to! seeing! so! many! exclamation! marks! at! the! end! of! names! in! my! code! (but that's a me-problem).
Ah that makes sense!:
Does it have any special meaning?
I should clarify that my initial disgust was from when I thought macros were defined by a special comment
what do you think about adding async in sqlalchemy (latest update)
I blame the person who introduced me to the libraries
but for some reason
marshmallow.EXCLUDE is not having any effect on my code anymore
oh dear
so when I do this
loaded_config_dict = ConfigurationSchema().load(data=loaded_config_dict, unknown=marshmallow.EXCLUDE)
marshmallow is raising a ValidationError since I have extra parameters
@ me in #tools-and-devops with a MWE
MWE?
minimal working example
or in this case MRE, minimal reproducible example
basically a small self-contained program that reproduces the issue
... that's gonna be hard but I'll try
its all contained in one file but I don't think I can get less than that
well... i don't envy you ๐ but one thing i've learned is, coming up with the MRE helps you find the bug 90% of the time
and if it doesn't, you basically start "bisecting" between your code and the MRE until you figure it out
yeah....
The syntactic macros' syntax is confusing
It seems.. counter-intuitive to Python being a friendly language, in terms of how it looks
I think there should be a much nicer syntax as @paper echo pointed out
What is the best no op dunder method to use on an instance? That looks as close as the instance name as possible when accessing it but triggering something within the class
The closest one I could use were the unary operator ones, since they look as close to the class instance as normal
i'd honestly be surprised if the macro stuff were accepted
but I've been wrong before
well, it was pointed out to me that the pep doesn't actually specify how to define a macro ๐
Ah
it just defines its internal representation and its semantics
hey
from enum import Enum, auto
import uuid
import pygame
class Keys(Enum):
ARROW_UP = auto()
ARROW_DOWN = auto()
ARROW_LEFT = auto()
ARROW_RIGHT = auto()
class Player(object):
"""creates a player and their methods."""
def __init__(self, name: str, x: int, y: int) -> None:
self.id = str(uuid.uuid4())
self._speed = 1
self._data = {'name': name, 'x': x, 'y': y}
@property
def data(self) -> dict:
return self._data
@data.setter
def data(self, value: dict):
if not isinstance(self.data, dict):
raise TypeError("data must be a dict.")
self._data = value
def key_pressed(self) -> Keys:
"""get the keys pressed by player."""
KEYS = pygame.key.get_pressed()
keys_list = [
KEYS[pygame.K_UP],
KEYS[pygame.K_DOWN],
KEYS[pygame.K_LEFT],
KEYS[pygame.K_RIGHT],
]
ALLOWED_KEYS = [
Keys.ARROW_UP,
Keys.ARROW_DOWN,
Keys.ARROW_LEFT,
Keys.ARROW_RIGHT,
]
if any(keys_list):
return ALLOWED_KEYS[keys_list.index(True)]
i created this class Player as you can c but think that the method key_pressed is in the wrong place bc the class player should just have the player info... not the input layer i suppose that the method key_pressed should be a function... I wanna know what do you think abt it.
If you really wanted it to be organized, you can either A: access it as another class itself entirely
Or b: if you want it to be organized separately but want it to be within the player class (I think this is best), you could make the key pressing into a descriptor by putting it in another class
descriptors implement __get__, __set__, __delete__, and __set_name__ (I think I"m missing something)
.rp descriptors
In this step-by-step tutorial, you'll learn what Python descriptors are and how they're used in Python's internals. You'll learn about the descriptor protocol and how the lookup chain works when you access an attribute. You'll also see a few practical examples where Python descriptors can come in handy.
ic
Has anyone ever looked at how CPython memory manages?
Is the allocation of memory just like:
how big is this object -> size class index -> corresponds to which pool to go to ->
if no pools available in the arena -> create a new pool -> once done, free the pool
if pools are available, just allocate the object to that pool
bc the game class have the method move_player that take 2 parameters the player object and the key pressed...
and moves the player...
Thank you! :D
also, very detailed comments in the source https://github.com/python/cpython/blob/main/Objects/obmalloc.c
yum
attr.fields(config().default.bot.__class__)[1].metadata[METADATA_TABLE].description
hey
Anyone know anything about Pythons AI uses in the medical field ?
modelling community spread of infections? modelling high dimensional data in the medical field, etc
There was this kaggle competition i looked through a while ago that had people use a series of MRIs of patients heads to determine if they had glaucoma
The winner used python, so theres that
anyone have experience with SVGwrite.py?
Hmm, what are some of yallz favorite libraries?
Hi can I ask some questions
?
so my question is simple ig
What services students need ??
What services do common people need in everyday life??
PLS ANSWER THESE QUESTIONS
!rule 8
8. Do not help with ongoing exams. When helping with homework, help people learn how to do the assignment without doing it for them.
This is not H.W
well
or exam
!rule 7
7. Keep discussions relevant to the channel topic. Each channel's description tells you the topic.
this channel is about python itself.
!ot you would likely have better luck in
Off-topic channels
There are three off-topic channels:
โข #ot0-psvmโs-eternal-disapproval
โข #ot1-perplexing-regexing
โข #ot2-never-nesterโs-nightmare
Their names change randomly every 24 hours, but you can always find them under the OFF-TOPIC/GENERAL category in the channel list.
Please read our off-topic etiquette before participating in conversations.
Meta Libraries
poetry for project management.
poetry is a project manager, like pipenv or pdm. Poetry also replaces setup.py, which is awesome.
Extremely good at what it does, but IMO tries to do too much.
twine for uploading builds to pypi
While poetry has support for this, given how only one shot is allowed for a push to pypi, I use twine. I do not want poetry breaking on this, since I use the alpha builds.
pipx used for installing python tools globally
the tldr: pipx is a wrapper for pip and venv, Long form: pipx makes venvs, installs tools, and adds them to path. Very very simple idea, flawless execution. I highly recommend this as a way to install any command line tool from pypi.
taskipy used for tasks.
This program is excellent. Allows defining tasks in pyproject.toml, so the same boring command can be ran just with task command This also enables repeatability, and saved keystrokes ๐
TOML
atoml for toml file parsing.
Style-preserving toml reader and writer. This is a fork of tomlkit, which is used in poetry. If not needing to preserve user style, could use tomli and tomli_w.
HTTP Libraries
aiohttp, httpx, httpie
These are not all comparable, but are worth listing together since they all perform the same action. However, there's some mighty big differences between the 3.
aiohttp is an asyncronous http library-- with websocket support. If websockets are needed, aiohttp is my goto library.
httpx is a drop-in replacement for requests. Its supposed to fix a lot of the problems with requests (do not quote me on this), but also adds many new functions for more features. In addition, it has an asyncrounous engine as well. However, it does not support websockets.
httpie is a library which is kind of an outsider on this list.
This is a replace for curl, and should be installed to a global venv, perhaps with pipx. Its pretty cool, haven't played with it too much tho.
Python style tools
black - the best formatter. #black-formatter for more info
flake8 - linter. TLDR its a combination of multiple other linting libraries.
GIT Related
Aight, this is a fun category, and I have an extra guest for it too. ๐
pre-commit runs before commits, catch errors in advance. Extremely easy to write your own hooks, too.
dulwich a complete python implementation of git. Yes, you read that correctly.
I'm not sure what the intended use case is, since if there's an existing git repository, git is already installed, but given that it can clone repositories, its actually incredibly useful.
Testing
pytest The best testing framework for python. Ofc, it means nothing if you don't write tests.
coverage.py (coverage) this is the way to get coverage for python.
Its best used with testing, and lets you know what code ran and didn't run with the tests. Please note: coverage is not the best way to write tests, and should only be an indicator that something ran. Whether it was actually tested or not, that is up to the tests.
I think that wraps up my favorite libraries, I'm interested in anyone else's favorite go-to libraries too ๐
... I think I was bored. No, I do not have a blog because if I did I would have posted this there.
You should get a blog haha
meh
discord.py
Easy to use, and itโs the library Iโve used while doing my open source contributions mainly.
asyncio
I know this is stdlib but I still really love it - even though Iโm incompetent at it, it is still very powerful regardless, and very useful for I/O, which is what I do commonly.
dis
YASL (Yet another standard library), though it has changed my general recent use of Python, and greatly helps me with when Iโm messing with bytecode and has even helped me learn it partly.
inspect
This is a bit more descriptive when inspecting source code and what not, and is useful for also messing around
why the function print makes my code slow??
Does anyone has any idea on Marketing Mix Modelling?
How does it make it slow?
This is a good list. I agree, you should post this somewhere more "persistent"
Taskipy looks interesting for systems that don't easily have access to GNU Make
I know people have used Tox for that in the past
I used to use Snakemake which i have grown to dislike
if you are doing a massive amount of prints it will slow it down, yes, as it is more things to do
you probably want sys.stdout.write but print provides more function tho
maybe sys.stdout.write is faster
it will most probably have really similar speeds
oh
If anything it could be slower
Python needs to lookup sys, then stdout and then write.
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)```
Print *objects* to the text stream *file*, separated by *sep* and followed by *end*. *sep*, *end*, *file*, and *flush*, if present, must be given as keyword arguments.
All non-keyword arguments are converted to strings like [`str()`](https://docs.python.org/3.10/library/stdtypes.html#str "str") does and written to the stream, separated by *sep* and followed by *end*. Both *sep* and *end* must be strings; they can also be `None`, which means to use the default values. If no *objects* are given, [`print()`](https://docs.python.org/3.10/library/functions.html#print "print") will just write *end*.
The *file* argument must be an object with a `write(string)` method; if it is not present or `None`, [`sys.stdout`](https://docs.python.org/3.10/library/sys.html#sys.stdout "sys.stdout") will be used. Since printed arguments are converted to text strings, [`print()`](https://docs.python.org/3.10/library/functions.html#print "print") cannot be used with binary mode file objects. For these, use `file.write(...)` instead.
uhh
Isn't print by default basically sys.stdout.write followed by sys.stdout.flush?
Do the printing in a separate thread ๐
It doesn't flush by default, the "only" thing it offers is the convenience of being a builtin and how it accepts and formats its args
so i'm wondering how rounding floats works on the backend, as in, how the round() function manages to round a float to a certain decimal place? i found https://github.com/python/cpython/blob/60b93d9e4922eeae25052bc15909d1f4152babde/Objects/floatobject.c#L926, but i can't understand the algorithm, and i when i try googling stuff like "how does python float rounding work", i get tutorials as to how to use round() rather than the algorithm round() uses
Objects/floatobject.c line 926
double_round(double x, int ndigits) {```
How do I typehint an int with the radix?
Something like value: int(base=16)
An int is an int, the base only really matters in its string representation
How would you expect that typehint to behave?
Throw error if the given int cannot be parsed into base 16 for example
So you want to take a string that represents a base-16 int?
You could use typing.Annotated or a custom alias for str
Since that is what you're actually passing
OK thanks
you're right, it says flush=False right above my post ๐คฆโโ๏ธ
unfortunately you can't do this currently in python. it would be very cool if we had a mypy plugin that could check if a string matched a certain pattern, but even then it would only work on either string literals or with a TypeGuard (3.10)
!pep 647
i'm not sure how those will integrate (if at all) with Annotated
So just use regex?
yeah, for now you have to specify it as a runtime constraint
Hello
while not enforceable beyond the type, a type alias goes a long way
i guess you can't parameterize a type with a string? that's a bummer https://mypy-play.net/?mypy=latest&python=3.10&gist=9897d119902d37e7e55ccbe8371bbb3d
let me try with Literal
actually i'm not even sure how that'd work
A frog wants to maximize their probability of reaching 1 on a number line from 0.00000001 after 100 turns. Each turn they can choose a number f between 0 and 1 and have 0.55 chance of multiplying their position by 1+f and a 0.45 chance of multiplying their position by 1-f.
This is pretty hard
You have to create an algorithm to maximize the chances of you reaching 1
on the number line
really interesting but hard
that sounds like a math problem
either #algos-and-data-structs or an ot channel
@wicked pumice
doesn't mean you can post it in an unrelated channel
there's examples in the socket lib docs iirc
i think this kind of thing belongs in a help channel.
has there ever been a serious proposal for destructuring mappings with =?
{'x': x, **_} = {'x': 1, 'y': 2}
that looks
incredibly esoteric
I understand it's idea being similar to foo, *_ = [1, 2, 3] but Idk
I would have liked {x, **_} = {'x': 1, 'y': 2}
requiring **_ for parity with ordered container destructuring makes sense
I'd put it on pypi, but there's not really much here that could go on pypi so I'll just link to it but tldr I made a configuration system which will export defaults to a toml file, yaml file, and a .env file:)
And uh, maybe I'll make a blog 
it's supported in 3.10 pattern matching already
that'd be nice too (javascript has {x} as an alias for {'x': x}) but i think it conflicts w/ set literal syntax and i don't think that can be reconciled
lst = ['Beans','Toast','Eggs','Bacon']
print("List before adding newline character to it:",lst)
lst = '\n'.join(lst)
print("List after adding newline character to it:\n",lst)
=Output
right, literals can appear on the left
is that advanced enough
wrong channel.
this is a channel for discussion of the language itself
np
Have fun
althoughโฆ
!e {1: 1}[1] = 1
@gleaming rover :warning: Your eval job has completed with return code 0.
[No output]
is there a reason no function would appear to have anything in __annotations__ ? and typing.get_type_hints() always returns {} (python 3.9)
false alarm, the annotations are there, there's just much less stdlib coverage than I expected
seems like typeshed covers much of stdlib?
then again stdlib has a lot of generics
..or does it?
i'm not sure, is typeshed something i can use in combination with stdlib, like if i have a reference to the function?
is it possible to type check a recursive type hint?
depends on the checker
typeshed provides stub files for the stdlib and some other packages, I don't think it's really accessible at runtime
Ah, gotcha
totally legal
from timeit import timeit
def f1(x=list(range(10000))):
x.reverse()
def g1(x=list(range(10000))):
for i in range(5000):
temp = x[i]
x[i] = x[-1 - i]
x[-1 - i] = temp
def f2(x=list(range(10000))):
return sum(x)
def g2(x=list(range(10000))):
total = 0
for n in x:
total += n
return total
print(timeit(stmt=f1, number=1000))
print(timeit(stmt=g1, number=1000))
print("- " * 20)
print(timeit(stmt=f2, number=1000))
print(timeit(stmt=g2, number=1000))```
Why is the time difference between list.reverse and doing it in python so much larger than sum and doing it in python? sum is only about 5 times as fast, but list.reverse is about 800 times as fast
I was thinking sum is still kind of slow because it needs to look up the value of the number in RAM, and it canโt put it in cache memory. list.reverse only needs to move around the whole python objects, so it doesnโt need to look things up in RAM as much
But it seems like neither would it need to when doing it in python
it's the power of compiler optimizations
what about reversed()?
a function in c that does the work of reverse or sum will be optimized into very efficient machine code
But sum isnโt that fast, while list.reverse is very fast
Hundreds of times as fast
as for why sum is so much slower, it would take more looking into it
i would expect interpretation to be some order of magnitude slower, but not sure how much
it's possible that the optimization gains from using c code simply aren't as heavy
IIRC bytecodes in python aren't really optimized at all too
Whatโs the bytecode telling the computer to do that makes it so much slower?
bytecode has to be translated into machine code
look at the disassembly of f1 and g1 for example
!e ```py
import dis
def f1(x=list(range(10000))):
x.reverse()
def g1(x=list(range(10000))):
for i in range(5000):
temp = x[i]
x[i] = x[-1 - i]
x[-1 - i] = temp
print("f1:")
dis.dis(f1)
print("g1:")
dis.dis(g1)
@sand python :white_check_mark: Your eval job has completed with return code 0.
001 | f1:
002 | 4 0 LOAD_FAST 0 (x)
003 | 2 LOAD_METHOD 0 (reverse)
004 | 4 CALL_METHOD 0
005 | 6 POP_TOP
006 | 8 LOAD_CONST 0 (None)
007 | 10 RETURN_VALUE
008 | g1:
009 | 7 0 LOAD_GLOBAL 0 (range)
010 | 2 LOAD_CONST 1 (5000)
011 | 4 CALL_FUNCTION 1
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/dewiruyufu.txt?noredirect
f1 is 6 op codes total
g1 is like 25, and like 20 of them are being looped through, so you end up with more like 100,000 op-codes executed total
each one needs to be executed separately by the python interpreter
that's a lot of overhead
So
one by one, through a big switch statement, internal functions called, etc
It canโt pre-load the instructions, or something?
It has to complete one, stop and load the next, complete that one, stop and load the next, etc?
cpython, as far as I'm aware, doesn't do that
pypy has a JIT compiler which is supposed to do some of that
a jit might
Why canโt it?
people have tried
Do you mean why can't it have a JIT (Cpython itself)?
it can, pypy is one implementation of python that tries and does to some extent
cpython is unlikely to have it though
Why canโt it load the instructions the bytecode will tell it to do before it gets to it?
^
There was a core dev talk that Python Disc hosted last year, and one of the questions was regarding a JIT coming to CPython, the core dev said it was highly unlikely as it would bea big undertaking
afaik the bytecode is interpreted line by line, so it can't predict the next opcode
(please correct me if i'm wrong)
yeah, they have side effects
Why canโt it do it?
it might have to jump for example
POP_JUMP_IF_FALSE(target)```
If TOS is false, sets the bytecode counter to *target*. TOS is popped.
New in version 3.1.
Ah, alright, so it is if statements i think for sure
Canโt it just stop and clear out the wrong branch it guessed and load the correct branch, like CPUs do with machine code?
that is way lower level stuff
and it is done, all cpus do it
even when running python
So itโs just a bunch of overhead piling up that makes it so slow?
I should make it clear that all the op-codes are preloaded into memory, if that's what you're asking about. That isn't where the overhead is coming from, it's literally the translation of bytecode into machine code that is slow
every python op-code has some c code associated with it which has to executed
literally a giant switch statement that says if the opcode is this, do that
for every opcode
iirc it's mostly python being interpreted that is one of the main factors of it being slow, another, smaller but still existent factor is dynamic typing
dynamic typing is one of the things that make python hard to optimize or jit
you can't make assumptions about the object you're working on
also it's running mainly having to read/write from the heap to get the objects I believe, which is a lot slower than registers, which C functions could use to manipulate values
here's a PEP you can look at to merge a JIT google developed, iirc the results weren't that amazing (and it required adding the whole LLVM to their source tree): https://www.python.org/dev/peps/pep-3146/#us
So list.reverse vs reversing in python, is python slower because the computer ends up needing to carry out hundreds of times more instructions? Or is it slower because somewhere along the way, the computer still needs to access stuff from RAM on each iteration, even though itโs still just moving around whole python objects?
a combination of both, although I think the amount of instructions that need to be executed would be the primary reason
sum isnโt very fast even though itโs compiled, Iโve assumed thatโs because it still needs to access each of the numeric values through pointers
But list.reverse doesnโt have that problem
yeah, it's likely because of that derefencing
a python list is contiguous memory filled with pointers to python objects, so reversing that is very simple, no dereferencing needed
summing requires dereferencing, and there is no guarantee that the integers will be in contiguous memory
also, might be also because sum has to look for the object's __add__ every time,
!e
class Test:
def __add__(self, other):
return 2
def __radd__(self, other):
return self.__add__(other)
print(sum([Test(), Test(), Test()]))
@surreal sun :white_check_mark: Your eval job has completed with return code 0.
2
hmmmmmmmmmmmm
ye, hashing is fun
trying to figure out the best way to store thes variables but I am not sure how I'll be accessing them. lol
ah, got it
pseudo-nested dictionary
Can someone tell me why can't I run this code?
Hey @bronze narwhal!
Uh-oh! It looks like your message got zapped by our spam filter. We currently don't allow .txt attachments, so here are some tips to help you travel safely:
โข If you attempted to send a message longer than 2000 characters, try shortening your message to fit within the character limit or use a pasting service (see below)
โข If you tried to show someone your code, you can use codeblocks
(run !code-blocks in #bot-commands for more information) or use a pasting service like:
it's a json? so i don't think it'll do anything unless you interact with it
and perhaps this is the wrong channel to ask lol
Wait is it?
No I actually don't know lol. I recently started Py at my uni. This code was given as an "example".
o
No idea why it didn't work.
maybe it isn't
there's no hashing involved for types defined in C, like int, AFAIK. It just looks at the type's .tp_as_number.nb_add slot.
oh this is an ipython notebook, you need ipython to open it i think
What's that
.-.
Ah.
Wait how do I open on Jupyter @warm kernel
I've never used it before. 
Opening jup takes me to this browser.
Sure.
This is already opened as BPO 35829 but I wanted to ask about it over here for discussion. Problem Statement The function datetime.fromisoformat() parses a datetime in ISO-8601, format: >>> datetime.fromisoformat('2019-08-28T14:34:25.518993+00:00') datetime.datetime(2019, 8, 28, 14, 34, 25, 518993, tzinfo=datetime.timezone.utc) The timezone ...

How do we get pattern matching but not the damn Z
python has never billed itself as supporting everything from a to z, has it?
(/j ofc)
oh god
that post, does enrage me
how can you support a format without supporting the full format??
this is like a json parser that fails parsing strings
oh man
I got that before
I thought it was a bug in JS
being a loyal Pythonista
TURNS OUT...
hmmmm
what are the true differences between os and sys? why are there two libs if most commonly, both are used?
sys interacts with the interpreter, not os
I'm less annoyed that it was omitted and more annoyed that there is so much resistance to adding it
There were some specific reasons offered, including "it's asymmetrical with isoformat" and "we need a better interface for this anyway"
Neither of which are good reasons imo
It seems like a pretty obvious concession to practicality to me, but there's a reason these people are core maintainers and i am not
I understand not doing it as it's easily replaceable by the user and not wanting to implement a full parser which would be complicated or outline what exactly it can parse, but then it's also a common pitfall
If it was already in python, would anyone be asking for its removal?
That's how i felt about my logging proposal too and why i was surprised to get pushback on it
yeah, there have been things removed and then readded
If it magically appeared in the language tomorrow, and nobody said "why is this here, it doesn't belong here", I think that's a good candidate for inclusion
Note: there are many things already in the stdlib that fail the "why is this here" test
https://discuss.python.org/t/how-do-we-want-to-manage-additions-removals-to-the-stdlib/10681/4 I've been sold on kernel python for a while now
but unless youโre explicitly advocating this for every module we remove then it seems out of scope for this general discussion. Yes this is what Iโm advocating, in fact Iโm explicitly advocating for the โkernel Pythonโ, remove everything that isnโt needed for running get-pip: https://bootstrap.pypa.io/get-pip.py Specially asyncio is a depende...
could you please provide one example? ๐
basically i wanna ask myself that question
From what it looks like to me the the main issue with things like adding the Z is deciding on what exactly to include and the discussions around it, like the question if it should be expanded beyond just the Z and in exactly what way
!pep 594
For sure. What bothers me is why it has to be any bigger than Z
The discussion is about Z in 2021, not about the ideal datetime parsing interface in 2023
I think generally the idea is to get if expanding its scope more is worth it if changes are already getting introduced (in this case Z alone may not be seen as worth it) but that leads to stalemates like this
!d fileinput
Source code: Lib/fileinput.py
This module implements a helper class and functions to quickly write a loop over standard input or a list of files. If you just want to read or write one file see open().
The typical use is:
import fileinput
for line in fileinput.input(encoding="utf-8"):
process(line)
``` This iterates over the lines of all files listed in `sys.argv[1:]`, defaulting to `sys.stdin` if the list is empty. If a filename is `'-'`, it is also replaced by `sys.stdin` and the optional arguments *mode* and *openhook* are ignored. To specify an alternative list of filenames, pass it as the first argument to [`input()`](https://docs.python.org/3.10/library/fileinput.html#fileinput.input "fileinput.input"). A single file name is also allowed.
this is extremely useless
pathlib, os, read, etc, for loops, not that hard to just... iterate all of the files yourself
We have discussed about new function in the json module, but we didnโt make decision about its naming. Previous discussion: Mailman 3 A shortcut to load a JSON file into a dict : json.loadf - Python-ideas - python.org Issue: Issue 43457: Include simple file loading and saving functions in JSON standard library. - Python tracker poll
ah right, I had a thought for the above:
https://www.python.org/dev/peps/pep-0594/#id205
why was it selected to keep??
gross
idc if a third party library has a function to load from a file, but the json library which is already extremely slow? ๐
Can anyone tell me, why the signature of the __get__-method ( __get__(self, obj, type): got obj as well as the objects type type? One could simply use the type-function on obj to determine the value if needed
https://www.python.org/dev/peps/pep-0594/#fileinput
Why do i get the feeling that this is only in "keep" because some core maintainers like it
Roll this functionality into argparse
Make a top level function to handle -
oh yeah, I've never used argparse
i figure if I'm ever gonna make a cli I'll use click
Good question, I've wondered this too. I assume there are cases when that doesn't work
but I suppose if I need a quick arg pass, maybe I'll just use argparse next time
but if I'm making something I intend to be public, I'll probably use click
idk really
afk
well, let's try stackoverflow
someone probably knows a cornercase
or this was needed back then and noone wanted to break stuff later
Ok there already is an explanation
I am reading the explanation of how descriptors work from the link: http://users.rcn.com/python/download/Descriptor.htm#properties.
But, here, under the class Property's get method, I have a d...
๐
is there a way to implement this?
Easily*
I could make a method which would recursively check
attrgetter?
wdym
In [9]: a=attrgetter("config.user.bot.prefix")
In [10]: from types import SimpleNamespace as sn
In [11]: bot=sn(config=sn(user=sn(bot=sn(prefix=0))))
In [12]: a(bot)
Out[12]: 0
I liked this one https://stackoverflow.com/a/18679700/2954547
I am reading the explanation of how descriptors work from the link: http://users.rcn.com/python/download/Descriptor.htm#properties.
But, here, under the class Property's get method, I have a d...
you could use functools.reduce maybe, with getattr
!d functools.reduce
functools.reduce(function, iterable[, initializer])```
Apply *function* of two arguments cumulatively to the items of *iterable*, from left to right, so as to reduce the iterable to a single value. For example, `reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])` calculates `((((1+2)+3)+4)+5)`. The left argument, *x*, is the accumulated value and the right argument, *y*, is the update value from the *iterable*. If the optional *initializer* is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If *initializer* is not given and *iterable* contains only one item, the first item is returned.
Roughly equivalent to:
>>> functools.reduce(getattr, "config.user.bot.prefix".split("."), bot)
0
or
from types import SimpleNamespace as sn
bot=sn(config=sn(user=sn(bot=sn(prefix=0))))
import __main__
functools.reduce(getattr, "bot.config.user.bot.prefix".split("."), __main__)
0
though operator.attrgetter is a bit cleaner
Because you don't always get the obj.
For example when it is used on a class, that's when you get the type
I would be more interested in learning about why __exit__ gets the error type and error (I don't think there's a case where you get one without the other).
is it the exception type and value? like what you get from sys.exc_info() - which also has the traceback
so you can reraise the error like
raise exc_type, exc_value, None
like @elder blade said, if the __get__ is for a class attr (think @classmethod) you might need the class it's geing called on because obj will be None (cause there's no bound object for the descriptor)
where did i see code like that.. oh right ๐
you will stop worrying and love the reduce() :)
i love reduce :p
Not sure if I'd be more inclined towards the attrgetter or reduce here, I guess both will be the same as it'd be abstracted away in a clearer func
but in combination with Path.__truediv__ etc it can turn into brain gymnastics ๐
still wonder if operator.truediv would work there
>>> class T:
... class Attr:
... def __get__(att,obj,type):
... print(att,obj,type)
... return 7
... a = Attr()
... b = Attr()
...
>>> T.a
<__main__.T.Attr object at 0x7ff715dd60> None <class '__main__.T'>
7
>>> T.b
<__main__.T.Attr object at 0x7ff715dd90> None <class '__main__.T'>
7
>>>
>>> T().a
<__main__.T.Attr object at 0x7ff715dd60> <__main__.T object at 0x7ff715d6a0> <class '__main__.T'>
7
>>> T().b
<__main__.T.Attr object at 0x7ff715dd90> <__main__.T object at 0x7ff715d7f0> <class '__main__.T'>
7
^ it looks better if the Attr has a nice repr that includes the name, obviously
>>> T().a
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized
And that's why you have to be careful with __repr__ ...
wtf..
!e
class Num:
class MultAttr:
def __init__(self, name):
self.name = name
def __get__(att,obj,type):
print(att, obj, type)
return obj._data * (1 + ord(att.name) - ord("a"))
def __repr__(self):
return f"<Attr {self.name}>"
def __init__(self, d):
self._data = d
def __repr__(self):
return f"<Num '{self._data}'>"
a = MultAttr("a")
b = MultAttr("b")
t1 = Num(1)
t2 = Num(10)
t1.a
t1.b
t2.a
t2.b
@lusty scroll :white_check_mark: Your eval job has completed with return code 0.
001 | <Attr a> <Num '1'> <class '__main__.Num'>
002 | <Attr b> <Num '1'> <class '__main__.Num'>
003 | <Attr a> <Num '10'> <class '__main__.Num'>
004 | <Attr b> <Num '10'> <class '__main__.Num'>
how do i get a reference to the function that called a function from inside? inspect stack only gives me a str..
and
import inspect
def get_keyword_param_names(locs):
func = globals()[inspect.stack()[1].function]
print(func, type(func))
return {name:locs[name] for name, param in inspect.signature(func).parameters.items()
if (
param.kind is inspect.Parameter.KEYWORD_ONLY
or param.kind is inspect.Parameter.VAR_KEYWORD
)}
def foo(*, a, b, **kwargs):
return get_keyword_param_names(locals())
s = foo(a=2, b=3)
print(s)
looks brittle
you can use the frame's globals but I don't think there's any better option
You could also parse the params yourself from the code object the frame is executing, I think it has everything you need for that
how would you do that?
function.__code__.co_varnames -> local variables within a function, includes parameters
ty
Np
would have to look into how inspect does it
Let me find the source code for inspect
probably through pos indices that are exposed through other co_ attrs in co_varnames and some co_flags
What are some great third-party tools/APIs that should be used be in production? I'm thinking like Sentry for error logging, Grafana for monitoring, etc.
- that depends on your "production" 2) there's #tools-and-devops for that subject
I'm looking for a list of the common ones that should be used in every project (like Sentry and Grafana)
looking at this code in typeshed, it seems invalid. array.array[Any] gives you a TypeError that subscript can't be applied to type() objects:
ReadableBuffer = Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap] # stable
WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap] # stable
shouldn't that be a type annotation, not an assignment?
It's probably a type alias used over the stub module
There were some other cases like that with invalid generics but I guess typecheckers understand them and it doesn't matter that it's not valid python as it's never ran
i see. there's a surprising amount of "scripting" in those type stubs, like it's not just simple assignments, so i thought maybe it could be executed somehow
but I guess it's meanmt for the big players (mypy, IDEs) that can already locate imports and infer types of things by parsing
I recall os.PathLike also having that "issue" but it looks like it got the syntax in 3.9
is there a reason the stdlib can't use inline type hints?
And well it is at least syntactically valid so you could leverage some parts like the parser, just not actually runnable
majority of it is in C that's not distributed with the install
ahh
For python modules I think they just don't want to introduce them into the files because of the potential maintenance and runtime cost when an alternative solution available
i see, well, it would be nicw if there was a package to grok the stubs for you
it seems crazy to parse two ASTs and try to match them up
is there another way it could work?
i would have preferred if they went with a declaritibe syntax
The current signature for sum is sum(iterable, /, start=0), but I wish it was sum(*values, *, start=0). Same with math.prod.
like
module = sys
[functions]
sys.breakpointhook = (*args: Any, **kwargs: Any) -> Any
sys.getsizeof = (obj: object, default: int) -> int
I usually have it the other way around e.g. asyncio.gather that accepts *aws instead of an aws iterable
agreed
guess it's a historic/compatibility thing
since we didn't have kw-only args when they designed it (I think?)
!d operator.attrgetter is there not a setter counterpart?
operator.attrgetter(attr)``````py
operator.attrgetter(*attrs)```
Return a callable object that fetches *attr* from its operand. If more than one attribute is requested, returns a tuple of attributes. The attribute names can also contain dots. For example:
โข After `f = attrgetter('name')`, the call `f(b)` returns `b.name`.
โข After `f = attrgetter('name', 'date')`, the call `f(b)` returns `(b.name, b.date)`.
โข After `f = attrgetter('name.first', 'name.last')`, the call `f(b)` returns `(b.name.first, b.name.last)`.
Equivalent to:
first.second.third.__setattr__ ? ๐
setter = operator.attrgetter("first.second.third.__setattr__")
setter(thing)(val)
might work?
nah, that would not work, would it
kw-only arguments were in an early version of python 3, I think. but I assume sum is very very old.
>>> setter = functools.partialmethod(functools.partial(operator.attrgetter("config.user.bot.__setattr__")(bot)), 79)._make_unbound_method()
>>> setter("age")
>>> bot.config.user.bot.age
79
works but quite hideous
yeah
python 1.6 maybe.. I think that's the oldest available
wonder if anyone was able to run it, certainly not me
is there a decent python parser that actually shows the source in its repr?
like returns the string of source code
ast doesn't or i would use that
So then it just checks that the object is an int, and then finds the method at a specific memory offset?
I don't think it checks that it's an int. I think it always looks up the function to call at that memory offset. For types defined in Python, I think the function at that memory offset does a lookup of the __add__ dunder and makes a Python call to it. For types defined in C, the function at that memory offset can just do the work.
At least, I'm pretty sure that's how it works, @sand goblet
Then does it need use hashing ever when you use operators? Or does it just reserve a specific memory location for the dunder methods?
And if you define it in python, then the function it looks up in C just looks up that memory location?
Or it canโt do that and still needs to use hashing for python defined classes?
I am trying to host a discord bot on replit and then monitor it on uptimerobot for it to be 24x7 online.
I am getting a 404 error when I monitor the HTTPS link. The problem is not resolved.
Things I did to troubleshoot
- Made sure the link is correct.
- Made sure the code works fine (it does, and it works perfectly when I run it from my browser)
- Made sure settings on replit monitor are correct as well.
Any help would be greatly appreciated.
Does it have to be repr? I'm sure you know you can dump resource source back out of an AST node
You could wrap the parse and dump functions into a class with the right repr
Does it dump source or just code that the AST represents?
it does have to be repr
i want to see what i am working with in the REPL without calling str() constantly
if I could override the repr function in one place that might be ok, but i don't know how i could set that up
since there'.s a bunch of different node classes
I would assume there would be an ipython hook you could use to create a custom repr for ast nodes
that's an interesting idea, I know there's sys.displayhook for the regular repl shell
Ah you're in the REPL, if yo uweren't in the repl, I would suggest stack() for seeing the source code as to how repr was called
I figured it out, although I'll probably do something with functools so it's more consise
Can post it shortly, but basically it uses operator.attrgetter :)
get_value = operator.attrgetter(option.rsplit(".", -1)[0])
setattr(get_value(self.bot.config.user), option.rsplit(".", -1)[-1], value)
Is there a way to convert something to the type of bytes you'd see in function.__code__.co_code?
Like bytecode represented with bytes in python itself
I want to convert a string into those bytes
Don't you use the AST module for that?
i mean, will running multiple instances cause you an issue? pls reply in #editors-ides ๐
no i just like hitting control R control R when debugging
don't wanna have to keep exiting
i close them all when i'm done
my record is in the 50s
that's how many processes i had open once
i was testing a bot for hours
ctrl shift f5
that restarts a debugging process in vscode
It's more of a runtime edit
but you can rebind the keybind & also pls use #editors-ides for vscode discussion
ty
So, for some reason, I now have a code object at the <module> level, and I want to get the code object wihtin it
because there's the function I want within that code object
how do I get the nested code obj
Python defined classes install a nb_add that looks up __add__ in the class's dict, I believe, which would require that hash table lookup. C defined classes have an nb_add that just does the work.
That is, no matter what, it calls the type's nb_add slot at a known, fixed offset from the start of the type object in memory. For built in types, that function does the work. For classes defined in Python, that function looks up the appropriate dunder (or dunders) and calls them, which requires a lookup (or lookups) against the type's class dict
Objects/typeobject.c line 8202
/* Common code for update_slots_callback() and fixup_slot_dispatchers().```
inspired from plusplus, I decided to try my own way to edit something dynamically
@patch_code("(x := x + 1)", "++x")
def hello_world(param):
x = param
if ++x == 2:
print("It's 2!")
else:
print(x)
hello_world(2)
>>> 4
replaces ++x with (x := x + 1)
Why canโt it reserve specific spaces in memory for dunders of classes defined in python? Would it take up too much memory to do that?
In what cases can all of the various argument combinations occur with __import__?
hey are you still open to helping people figure out smart contracts and python
anyone have any experience working with MTP/pymtp; accessing file directory of device/phone mounted on your PC? the library pymtp library doesnt seem to be working
getting the following error:
>>> TypeError: LoadLibrary() argument 1 must be str, not None
....
this idea is cursed
but basically I need to split a string on all capitalized letters
re.split
re.split(pattern, string, maxsplit=0, flags=0)```
Split *string* by the occurrences of *pattern*. If capturing parentheses are used in *pattern*, then the text of all groups in the pattern are also returned as part of the resulting list. If *maxsplit* is nonzero, at most *maxsplit* splits occur, and the remainder of the string is returned as the final element of the list.
```py
>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']
hmmmm
HowCouldIConvertThis to How could i convert this?
!e ```py
import re
print(re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9])\s(\s*):',r'static PyObject*\npy_\1(void)\n{','def myfunc():'))
@white nexus :white_check_mark: Your eval job has completed with return code 0.
001 | static PyObject*
002 | py_myfunc(void)
003 | {
how in the world does this work
like this ๐
!e ```py
import re
print(re.sub(r"([A-Z])", r" \1", "HowCouldIConvertThis"))
@white nexus :white_check_mark: Your eval job has completed with return code 0.
How Could I Convert This
Yes, that's the idea, but why are we in #internals-and-peps ?
because previously I thought it was extremely complicated ๐
& then sent the answer because finding questions with no answers is extremely annoying ยฏ_(ใ)_/ยฏ
Well, even if it is a complex question, it should go in a help channel. This channel is for discussions around the language itself.
Questions that messes around with the Python internals are probably fine too
hi hi does anyone here know how to rewrite tensorflow v1 keywords to v2
Hey @wise comet! This channel is for discussions related to the language itself, have you looked at #โ๏ฝhow-to-get-help?
sure thanks
.oO(iron man looking for help, that's a first)
is it considered normal for python to create (and set tracebacks for) 184 exceptions during interactive startup?
could be slowing things down, or at least using a lot of memory holding onto so many FrameType objects?
I have a doubt. Why doesnt python have anonymous functions like javascript?
builder.queryType({ fields: (t) => ({ hello: t.string({ args: { name: t.arg.string(), }, resolve: (parent, { name }) => `hello, ${name || 'World'}`, }), }), });
I know there's lambda, but it's not multi line. Are there any better options?
Pls ping me when help, thanks!
lambda
is an anonymous function
by definition
but yeah they kinda suck in Python
I mean you could always use ; which is a newline essentially but packed into one line in your code, though you can only do expressions for it
JS is also heavily callback based
; is invalid in a lambda as it's a part of the statement syntax
that's a meaningless statement unless you're planning on writing unmaintainable code
Python doesn't and most probably won't have more freedom with lambdas so you're forced to use normal functions, that's it
doesn't mean you can work around it in a lambda
i think it was one of the misconceptions regarding lambda that restricting it to a single statement would somehow make it safer, but just like with eval, you can break out of it and do whatever you like
i've seen horrifying exploits involving generators etc that would work around the limitation
sure, but you won't see that in any real application that has reasonable maintainers
But ; is just invalid as it's used for chaining statements which can't exist in a lambda in the first place
yeah
problem is that the restriction doesn't matter from any reasonable standpoint
if it's about security, you can work around it and if it's about clean code - the workaround is even messier
I don't think multi statements lambdas would really fit in syntax wise
i do
there's a couple of scenarios where you need a function that is called exactly once in the code, so naming it doesn't make much sense in many cases
so, you're stuck with a def _(): which is even worse on many levels
Why doesnโt list have certain methods that other objects do, like set.discard or str.replace or str.translate? And will they ever add those? Or do they not want to add any other methods?
discard is del l[i:i+1], replace and translate probably just aren't useful enough to be added. You could probably get a list method added if it were needed, there is definitely a usecase for .get when traversing json.
What about list.remove, but an error doesnโt happen if it canโt find the value?
that one could make some semblance of sense, but even then it is trivial to just make as a helper
i think it's primarily because you could keep coming up with "potentially useful" methods, and you just have to stop somewhere.
yeah, as of right now there are enough things in list IMO. If you really need complexity, there is always numpy
!pep 594
it would make sense to have a keyword switch like no_exception or somesuch for that
no need for another method
the replacement method for strings suck, it should take a dict
I wonder why set.remove has a separate method, set.discard, for no exception instead of something like that
I heard the reasoning was something to do with indentation?
idk how multiline lambdas relates in any way to security
Then that would replace re.sub, right?
And I guess str.translate too
translate is closer, re does much more
It replaces any pattern that matches, not specific substrings
that was 15 years ago.. and then he came and pushed for := ...
which could be said isn't pythonic either, so no point there
the "illusive trait" that mostly corresponds to "being pythonic" is probably "executable pseudo-code"
but nobody writes "lambda" in pseudo-code, so not even a point there
Lambda calculus (also written as ฮป-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation that can be used to simulate any Turing machine. It was introduced by the mathematician Alonzo Church in the...
the syntax used in lambda calculus itself is (x,y) ->
I always thought of Pythonic as using the most understandable approach to something, for example, using datetime.strptime to convert a YYYY-MM-DD string to a datetime object, rather than parsing it yourself
so if the idea was to base the whole thing on the idea of lambda calculus, then he should've taken the syntax as defined there and not make up a keyword nobody outside of math or CS would understand (and even then only barely)
I would honestly like anon as the keyword instead, or anonymous
Ofc a soft keyword
for an anonymous function
would make more sense to anyone coming from outside of those fields, yes
But thatโs just me ig
but imo it doesn't need a keyword
That would be a separate method, right? Instead of a change to str.replace itself?
I would agree with that but then beginners would be confused (the str.replace)
the way replace is build, it probably wouldn't work with a method-dispatch, so yeah, it would need a seperate method for clarity, probably
that's a lovely notion
I feel like thatโs probably how people use re.sub a lot of the time, as a substring replacer
When theyโre replacing more than just individual characters
what is "most understandable" depends strongly on the background someone has - a mathematician will know lambda calculus well, someone who just wants to script their inkscape will probably not
on the other hand, lambdas are everywhere in GUIs or networking as callbacks, but almost non-existent in scripts (which was probably the reason why GvR was shocked when people protested when he suggested to remove lambdas in general)
it's actually kind of ironic
the people (artists, GUI-designers etc) who need it the most are those who don't have the background to understand it at a glance
ah, the haskell approach
(\x -> x + 1)
though how a "\" looks like a "ฮป" is a mystery
Fair
it's just missing the little leg on the left
the buffet table pattern i came up mostly is as elegant as it is thanks to the lambdas, but it's severely limited - for instance, i can't easily insert logging statements etc. before the function-chain is called
as a reminder:
case_func = {
(False, False, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
(False, False, False, True): _pebkac_no_version_no_hash,
(False, False, True, False): _import_public_no_install,
(False, True, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
(True, False, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
(False, False, True, True): lambda **kwargs: _auto_install(_import_public_no_install, **kwargs),
(False, True, True, False): _import_public_no_install,
(True, True, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
(True, False, False, True): _pebkac_version_no_hash,
(True, False, True, False): lambda **kwargs: _ensure_version(_import_public_no_install, **kwargs),
(False, True, False, True): _pebkac_no_version_hash,
(False, True, True, True): lambda **kwargs: _pebkac_no_version_hash(_import_public_no_install, **kwargs),
(True, False, True, True): lambda **kwargs: _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **kwargs), **kwargs),
(True, True, False, True): _auto_install,
(True, True, True, False): lambda **kwargs: _ensure_version(_import_public_no_install, **kwargs),
(True, True, True, True): lambda **kwargs: _auto_install(_ensure_version(_import_public_no_install, **kwargs), **kwargs),
}[case]
result = case_func(**locals())
that's how it looks like
This seems unreadable. What are all of the bools for?
I really feel like a data class or enum or something would be more readable
What's a truth table?
it's a flattened decision tree, basically
~200 lines of if/elif code in one table ๐
yup
instead of a large if/elif tree, there's a single check for each var and a lookup in the table for the combination
This singlehandedly justifies pattern matching in Python.
it's a different mechanic though
What do you mean?
pattern matching works with if/elif basically, a table doesn't
but out of curiousity, how would you implement that buffet table as a case/match?
do you think arbitrary-width integers by default, as in Python, are a good design choice?
i do. makes prototyping much easier if you don't have to care about those details at first
Probably something like```py
match case:
case (_, _, False, False):
result = ImportError(Message.cant_import(name))
case (True, _, True, False):
result = _ensure_version(_import_public_no_install, **locals())
case (False, _, True, False):
result = _import_public_no_install(**locals())
case (False, False, False, True):
result = _pebkac_no_version_no_hash(**locals())
case (False, False, True, True):
result = _auto_install(_import_public_no_install, **locals())
case (True, False, False, True):
result = _pebkac_version_no_hash(**locals())
case (False, True, False, True):
result = _pebkac_no_version_hash(**locals())
case (False, True, True, True):
result = _pebkac_no_version_hash(_import_public_no_install, **locals())
case (True, False, True, True):
result = _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **locals()), **locals())
case (True, True, False, True):
result = _auto_install(**locals())
case (True, True, True, True):
result = _auto_install(_ensure_version(_import_public_no_install, **locals()), **locals())
๐ข
My understanding is that implementations can choose to compile pattern matching to a table.
not really much of an improvement imo ๐
It's just as ugly, but much clearer.
i don't think so
the code between the cases makes it harder to quickly check for a specific combination
An alternative where everything lines up:```py
match case:
case (_, _, 0, 0):
result = ImportError(Message.cant_import(name))
case (1, _, 1, 0):
result = _ensure_version(_import_public_no_install, **locals())
case (0, _, 1, 0):
result = _import_public_no_install(**locals())
case (0, 0, 0, 1):
result = _pebkac_no_version_no_hash(**locals())
case (0, 0, 1, 1):
result = _auto_install(_import_public_no_install, **locals())
case (1, 0, 0, 1):
result = _pebkac_version_no_hash(**locals())
case (0, 1, 0, 1):
result = _pebkac_no_version_hash(**locals())
case (0, 1, 1, 1):
result = _pebkac_no_version_hash(_import_public_no_install, **locals())
case (1, 0, 1, 1):
result = _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **locals()), **locals())
case (1, 1, 0, 1):
result = _auto_install(**locals())
case (1, 1, 1, 1):
result = _auto_install(_ensure_version(_import_public_no_install, **locals()), **locals())
heh
there's a nice boon for match/case though
it gets rid of the lambdas
on the other hand, the result = is a bit more verbose
That's the main thing I was looking at. Lambdas are scary.
yeah, you've got a point
It could get extracted into its own function with a return instead of a result =, and each case could be on a single line.
i'll consider moving to match/case when we drop the older python versions
how would that look like?
def choose_thing(case, **kwargs):
match case:
case (_, _, 0, 0): return ImportError(Message.cant_import(name))
case (1, _, 1, 0): return _ensure_version(_import_public_no_install, **kwargs)
case (0, _, 1, 0): return _import_public_no_install(**kwargs)
case (0, 0, 0, 1): return _pebkac_no_version_no_hash(**kwargs)
case (0, 0, 1, 1): return _auto_install(_import_public_no_install, **kwargs)
case (1, 0, 0, 1): return _pebkac_version_no_hash(**kwargs)
case (0, 1, 0, 1): return _pebkac_no_version_hash(**kwargs)
case (0, 1, 1, 1): return _pebkac_no_version_hash(_import_public_no_install, **kwargs)
case (1, 0, 1, 1): return _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **kwargs), **kwargs)
case (1, 1, 0, 1): return _auto_install(**kwargs)
case (1, 1, 1, 1): return _auto_install(_ensure_version(_import_public_no_install, **kwargs), **kwargs)
ah!
Discord highlighting is grating me a little.
yeah, that's not too bad, although choose_thing would be an ideal case for a lambda ๐
as an actual anonymous function
That would mean going back to the dictionary and lambdas, because match isn't an expression.
nah, i mean if we had actual lambdas
not the pseudo lambdas we currently have ๐
This would look a little cleaner in Rust.
Match expressions, no case keyword and blocks of code in lambdas.
That's what I'm internally comparing Python to.
Anything to help stop lambdas from creeping in everywhere.
hrhr
Would a dict be enough, or would it need to use a trie or ternary search tree or something else?
Imagine writing justuse in rust then making a public api written in python
heyo
where should I go to talk about good practices and the pythonic way?
i'm wondering what's the proper way to catch a specific excapction according to y'all
"""
1. Create a pyqt window
2. Set the application layout as a grid layout
3. Create 3 tabs each with one button
3. Button 1, exits the application
4. Button 2, prints "Hello world" to console
5. Button 3, opens a new window.
"""
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QTabWidget
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("PyQt5 Tab Widget")
self.setGeometry(350,150,600,600)
self.UI()
def UI(self):
vbox = QVBoxLayout()
tabWidget = QTabWidget()
button1 = QPushButton("Exit")
button1.clicked.connect(self.exitWindow)
tabWidget.addTab(button1, "Tab 1")
button2 = QPushButton("Print to console")
button2.clicked.connect(self.printToConsole)
tabWidget.addTab(button2, "Tab 2")
button3 = QPushButton("New Window")
button3.clicked.connect(self.newWindow)
tabWidget.addTab(button3, "Tab 3")
vbox.addWidget(tabWidget)
self.setLayout(vbox)
self.show()
def exitWindow(self):
self.close()
def printToConsole(self):
print("Hello World")
def newWindow(self):
self.nw = NewWindow()
class NewWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("New Window")
self.setGeometry(350,150,600,600)
self.UI()
def UI(self):
self.show()
def main():
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec_())
if __name__ == '__main__':
main()
This was generated by OpenAi's GPT-3 Codex.
I am in awe
holly
how does the grid layout look? Sensible values for the parameters?
it looks like this
lmao
pretty good for an ai though
The buttons do what they are supposed to do as well
also thought this was pretty cool (also generated with GPT-3):
"""
1. Create a function called SendEmail
2. The function will take message, to, from, password and subject parameters.
3. Send email message
"""
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def SendEmail(message, to, from_, password, subject):
msg = MIMEMultipart()
msg['From'] = from_
msg['To'] = to
msg['Subject'] = subject
msg.attach(MIMEText(message, 'plain'))
server = smtplib.SMTP('smtp.gmail.com: 587')
server.starttls()
server.login(from_, password)
text = msg.as_string()
server.sendmail(from_, to, text)
server.quit()
SendEmail("Hello", "to@gmail.com", "from@gmail.com", "password", "Subject")
that's nuts
I agree
wait, that's autogenerated?
Yes, it is.
"""
1. Create a function called SendEmail
2. The function will take message, to, from, password and subject parameters.
3. Send email message
"""
These were the instructions I gave it.
hehehe ๐ yeah, well. another lifetime, perhaps ๐
yeah, copilot is quite impressive at first glance, but i'd be very careful about generating such long code
you need to understand the code yourself 100% and make sure it doesn't mess up the details (which happens quite a bit)
it also tries to be helpful in generating comments, but it messes up majorly
like when you try simple maths like # 23923 * 34983 = it would put an arbitrary number in, which feels like "there, i know the solution, just believe me" although it's completely wrong
another instance was when i had a complex algorithm and copilot suggested a - on first glance legit - stackoverflow url
but when i clicked the url, it was obvious copilot had taken a valid but completely wrong url, chopped off the str after the post id and put a string there that appeared to be related to the code i was working on
it completely lied to me
i dread the day newbies use copilot to build their stuff and then whine about how "the AI takes their jobs away", then use a tool like that and whine about how "you still need to know how to program, boo!"
If you start with buggy code, copilot will intentionally* write more buggy code, because that's what it expects would come next.
- Shorthand, although it's not easy to prove it does things intentionally.
and if you start with nothing, it'll give you random nonsense
and more often than not copilot produces crap like
@__call__.register(None, str, str, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool,)
:p
rolls around in pandas
I have a newfound respect for language designers
this parsing thing is hard
Wait this is from pandas?
I mean, pandas method signatures
a lot of them look like that
Ah yeah
no, that snippet is a function i decorated with singledispatch
and copilot added the whole idiotic bool rest without a hint of intelligence :p
"artificial intelligence" my ass
That actually reminds me, there should be a way to decorate with an instance's methods.
class Test:
def __init__(self, callback):
self.callback = callback
self.intelligense = -1
def intelligence(...):
...
@.intelligence(2)
@Test
def dummy():
...
# So that it becomes
def dummy():
...
dummy = Test(dummy)
dummy = dummy.intelligence(5)
I've had some use-cases but resorted to helper functions that basically make that required call.
@elder bladehow about operator.methodcaller
Interesting, yeah that could actually work
grml.. why can't i use singledispatch to dispatch on None ๐
Have you tried NoneType?
Since None is used as a shorthand for its own type in type hints
It's available in types IIRC, and ig you could also use type(None)
yeah, i worked around it with type(None)
annoying nevertheless
the error message was also not really helpful, just saying "can't take None"
ahh, then i'm to blame myself
i wrapped the wrapper to implement a method-singledispatch
def methdispatch(func) -> Callable:
dispatcher = singledispatch(func)
def wrapper(*args, **kw):
# so we can dispatch on None
if len(args) == 1:
args.append(None)
return dispatcher.dispatch(args[1].__class__)(*args, **kw)
wrapper.register = dispatcher.register
update_wrapper(wrapper, func)
return wrapper
yeah, i missed .__class__
that's probably cause of the glitch
:incoming_envelope: :ok_hand: applied mute to @cursive stone until <t:1632490787:f> (9 minutes and 59 seconds) (reason: discord_emojis rule: sent 22 emojis in 10s).
i wished there was a proper method-singledispatch..
!d functools.singledispatchmethod
class functools.singledispatchmethod(func)```
Transform a method into a [single-dispatch](https://docs.python.org/3.10/glossary.html#term-single-dispatch) [generic function](https://docs.python.org/3.10/glossary.html#term-generic-function).
To define a generic method, decorate it with the `@singledispatchmethod` decorator. Note that the dispatch happens on the type of the first non-self or non-cls argument, create your function accordingly...
uhhh
You'd get an AttributeError appending to a tuple
must've been added since i last checked the documentation for singledispatch ๐
thanks!
yeah, singledispatch is from 3.7, singledispatchmethod is 3.8.. makes sense
It was a relatively recent addition, yeah
another 10 lines of code removed, nice
anyone have experience in libcst?
theres so much and i cant make heads or tails of it
i found out it can read pyi files like https://github.com/numpy/numpy/blob/v1.21.0/numpy/ma/__init__.pyi and i want to get stuff like
numpy.ma.core.maskedarray
so hard to read tho
reminds of xml :p
ast tree was already a headache and this is harder
i appreciate some guidance if anyone is willing to give some
please ping if you do i'll do more research
Yeah, I read through it before running it dw ;)
does it even work on more complex functions that arent just "grab a SO answer and modify the arguments slightly"
Hello
it feels like a crutch for language/library limitations
and any fully functional coding ai would still require you to program
just that the programming language is now your "high level" step by step description instead of a "lower level language" like python
close but not quite. if it was a proper "high level" language, there would be little ambiguity what the result will be, but copilot's generated code is entirely unpredictable
and not reproducable
it really is more a tool for inspiration in that case
a quite fun one, tbh
what do you mean "fully functional"?
oh, it works
you just need to be vigilant
much like those cars that can drive semi-autonomous
you wouldn't say they "don't work" just because they can't handle all situations, but it's a nice comfort to have if you can kick back on a boring route
name = f"{package_name}:{module_name}" or = f"{package_name}/{module_name}"? any preferences?
second one
slash it is
looks like what nodejs and go (?) use
ASGI uses the former afaik?
folder.folder.file:object
next AI assistant should work on AST nodes, not text
I think the result would be someehat better
why can't you post it in a help-channel or here?
well, is the question advanced?
this channel is for discussion of the language itself
discussion of use cases, implementation..
maybe all the help channels could be combined into one, what could go wrong .
the one issue with slash and dot is , if you replace slashes with dots, you lose the separation
or vice-versa
i like slashes, it corresponds nicely to Path
backslashes have a different meaning in strings
indeed.. on sane platforms
i don't know about go etc, but it's not a bad thing to go a path well-wandered
pun intended ?
lol
so when do we get __pypackages__/
did I misremember the name? that local module dir thing
!pep 582
In general
What's the best way to reduce a user's exposure to a certain segment of a codebase?
Make it as hard to read as possible
Python has no privacy. I have some code that is really, really best left untouched. I don't want to explicitly stop someone from playing with it if they really want to, but I'd like it obviously private (moreso than just with underscore-notation)
oh god, no :p
put it in a seperate module with a fat disclaimer?
You make programmers cry
I'm sure between all out big squishy brains we can come up with something
# DO NOT TOUCH OTHERWISE ALL HELL BREAKS LOOSE
or rather # THIS CODE IS AUTO-GENERATED AND WILL BE OVERWRITTEN IF MODIFIED
I'm writing a graphics library for python, one which leverages web graphics by creating a pythonic clone of the DOM in the page. Make sense?
then people will keep their hands off :p
Changes to these clone elements are transmitted to Javascript in real time
who will see it
Nowโfor a whole host of reasonsโany element manipulation (of these python clone elements) takes place in a subprocess of the main application process.
And thats fine. The user can do whatever they want with all that
But I'm typing away this morning and I realized, I'm going to have to parse the HTML before the window is launched, manipulate it, rewrite it, and then launch the window to display it
calling the cops now... โ
So unfortunately, I have to maintain a 'live template' of an HTML document within the main application process. This live template is the parsed and objectified version of the raw HTML text document the user is launching
Does all that make sense?
My thing is, and I don't really know why except that my instincts tell me so, I'd like to dissuade the user from screwing around with the innards of this template
like beautifulsoup? but for graphics
Sorta
you could do some inspect magic and raise a warning when accessed, but if isn't part of the API, just the _ should be enough
Beuatiful soup parses a document. Mine parses a document, and establishes a connection to the live-and-rendered version of it running in a browser. Changes to the parsed dom get reflected in the live version
if your users ignore the obvious signs of "internal api" and continue, they either know what they're doing already, or are hopeless cases
what mechanism are you using to communicate state with the browser
I understand this perspective, but philosophically I've always taken a bit of a different take. I think the boundary between a public API and a private one should be lined with alligators, black knights, spikes, and giant spiders
With Python, is more of a suggestion than anything. I'm just going to put this out thereโthere is always the nuclear option of privatizing this segment of the API using Cython
just use double underscore as extra privacy
That remains to be seen. The python-powered webbrowser I use is called CEFPython and you can use it to directly call JS functions from python, and vice versa
but imo it doesnt really matter
don't do that
it doesn't add anything and only leads to annoyance
dunders are only useful if you require name-mangling
Unfortunately, the cefPython 'browser' object exists in the main application process and is unavailable to the window process in which the elements live. I could always use message passing (windowProcess -> applicationProcess -> JS, or reversed) but I think a direct connection via websocket will be better
which you very rarely need
i concur
I guess a big part of this comes down to how the Template object is used. In the application process, I need to parse HTML document, and inject into it a bunch of script and stylesheet (link) elements
These script elements are the Javascript-side of the API, and are needed to communicate with the python runtime
also concur
So there's three steps to launching the application. Create the application object (thereby initializing the framework), create a template object (providing to it the location of an HTML document), and create a window object, providing to it a template object to render
Does that seem logical?
That template contains elements. I'd prefer those elements be 'out of the way'
window is meant to mirror the entire chromium window? or just a document?
A 'window' is actually a wxpython frame widget with a cefpython 'browser' object embedded inside. A browser o ject is an html renderer and a link to a running js running, associated with the page being rendered
Running js runtime*
oh, so it's like a window with a webview embedded
That's not even astronomically crazy
looking at the CEFPython code, they do the single-underscore thing too, so if anyone could shoot themselves in the foot, I'd think they'd have already done so with CEFPython
I would say that we differ greatly in how we think, I am usually of the mentality that you should never stop the user from themselves. If someone wants to fuck themselves over then be my guest y'know
im always annoyed when i see the program I'm trying to use has child locks on it
or its intentionally obfuscated to hide the python source,,etc. just makes me more determined to break its encapsulation ๐
Its not so much that I want to stop the user from accessing something. Go! Do! Learn, make mistakes, have fun
Its that I want the API to be simple, and beginner friendly
And that means hiding the nitty gritty from view, so its only there if you're intentionally looking for it
And in that case an _ will be enough to hide what you want
There's also the fact that if you expect a user be interacting with something, there is an expectation of unambiguity required in its design. Best practices must be followed to the letter, clean and unambiguous error messages, and redundancy needs to be in place
