#esoteric-python
1 messages · Page 43 of 1
gonna search it up though
!e the same thing applies to integers smaller than 256
print(id(256 - 1) == id(255)) # True
how tf did I wrote ì as a typo?
:white_check_mark: Your 3.12 eval job has completed with return code 0.
True
don't know on how many other things this applies tbh
256 included, [-5; 256]
is my memory that bad?
id(256) gives me 140733508675992 on 3.12
140720383670680 for me
also on 3.12
3.12.3
(tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)] on win32
print(id(301 - 1) == id(300))
This is also true for me.
why it wouldn't?
They wrote above that it's only true for [-5; 256], but maybe I misunderstand.
!e ```py
n = 10000
def _range_list():
[()for()in range(n)]
def _mul_list():
[()]*n
import dis
print(dis.dis(_range_list))
print("===================================\n")
print(dis.dis(_mul_list))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 2 0 RESUME 0
002 |
003 | 3 2 LOAD_GLOBAL 1 (NULL + range)
004 | 12 LOAD_GLOBAL 2 (n)
005 | 22 CALL 1
006 | 30 GET_ITER
007 | 32 BUILD_LIST 0
008 | 34 SWAP 2
009 | >> 36 FOR_ITER 5 (to 50)
010 | 40 UNPACK_SEQUENCE 0
011 | 44 LOAD_CONST 1 (())
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ZMNJ4LEJFW5RU6X7DIJPX4FOOQ
the second is just getting optimized by the interpreter
!e
test = lambda: 10**5
import dis
dis.dis(test)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1 0 RESUME 0
002 | 2 RETURN_CONST 1 (100000)
are there any other examples when python would do some simple calculations during compilation?
!e
test = lambda: 5+2*3+25**2
import dis
dis.dis(test)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1 0 RESUME 0
002 | 2 RETURN_CONST 1 (636)
!e
test = lambda: 5+2*3+25**2+2.0
import dis
dis.dis(test)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1 0 RESUME 0
002 | 2 RETURN_CONST 1 (638.0)
oh, it can do a type coercion
that's true for a different reason
i don't have time to explain it yet since i need to go to school :>
301 - 1 compiles down to 300
constant expression folding
so its really id(300) == id(300)
!e ```py
import dis
dis.dis("id(301 - 1)")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 PUSH_NULL
004 | 4 LOAD_NAME 0 (id)
005 | 6 LOAD_CONST 0 (300)
006 | 8 CALL 1
007 | 16 RETURN_VALUE
see the LOAD_CONST (300)

!e ```py
x = 301
exec(f"print(id(x - 1) == id({x - 1}))")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
False
!e ```py
x = 301
print(x-1 is x-1)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
False
simpler
from -5 to 256*
(in vanilla cpython)
..who pinged me =へ=
oki
a
bcdefghijklmnopqrstuvwxyz&
@fallow ingot please use #bot-commands for testing code
oh sorry
no problem
Yo
since when does dis.dis exist? like, where did that come from?
it came from python2
why does it use print as output generator?
because it is a debugging tool
K makes sense
it's existed for years
doesnt returning your code as a data structure would be nice as well? or there's AST for that, (even though, this seems more powerful, haven't readed the entire file but, yk)
dis.Bytecode exists, I still don't like it though, and dis.Bytecode.dis returns a buffer instead of printing everything
its already as bytecode
with compile
yeah but I mean something like List[Instruction], but something a little bit more structurized, and Instruction with cached dissasembled data instead of recalculating it each time Instruction._disassemble is called
that's why I don't like just having that Bytecode
?
instead of raw bytecode, a struct Instruction containing information about the decompiled instruction, and if they were structurized in functions out of a module or something like that, it would also be useful for code-analizing tools; something like
dis(x, *, file=None, depth = None) -> List[Instruction] | Dict[str, List[Instruction]] | Bytecode (Bytecode because it could have it's input buffered and have smth like disassemble(2) which disassembles 2 instructions and gives that to you, some sort of buffered disassembly)
that may have not many usecases but seems more, idk, usable than printing everything as it's being disassembled instead of creating it into a data-object and then making functions to represent that
i dont know what all of the annotations are supposed to mean
list[T] is a list of T's, e.g., [1, 2, 3] is a list[int],
dict[K, V] is a dict where keys are of type K and values are of type V, e.g. {"x": 1, "y": 2} is a dict[str, int]
| is well, union, A | B -> either an A, or a B
yes i know the literal meaning of all the notation
thats not what i meant
so what do you not know 
why a function would do this
List[Instruction] | Dict[str, List[Instruction]] | Bytecode
seems like a very weird design!
perhaps
dis.get_instructions()
i thought this was common knowledgee =~=
didn't know it existed, thanks
chronioc esopy dweller syndrome
CEDS
DEES-N
Depraved Esopy Enthusiast Syndrome
anjnj.
yes it is you silly goose
you've been here for more than three months, after all
Are there anyway to make so NameError is not raised but instead make it as a variable with a object of a custom class
Oh, nice idea, haven't thought of that
i thought this was common knowledgee =~=
But you have to think of the knowledge
And well, I failed to make it lul
!e ```py
from ctypes import py_object
class A:
def init(self, x):
self.name = x
class globols(dict):
slots = ()
missing = lambda _, x: A(x)
py_object.from_address(id(globals())+tuple.itemsize).value = globols
print(b)
:x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 11, in <module>
003 | print(b)
004 | TypeError: 'A' object is not callable
ehh =-=
print is not a global variable, so A() is assigned to it
it actually is though isnt it
at least here
!e
skibidi = "def"
dop = "main"
dоp = "()"
yes = " -> "
yеs = " None:"
hi = "print("
mark = "\"Hello, World!\")"
уes = "if __name__ == \"__main__\":"
уеs = "main()"
exec(f"""
{skibidi} {dop} {dоp} {yes} {yеs}
{hi} {mark}
{уes}
{уеs}
""")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
Hello, World!
unicode abuse! !!
!e grr ```py
from ctypes import py_object
class A:
def init(self, x):
self.name = x
class globols(dict):
slots = ()
def missing(_, x, builtins=builtins):
try:
return builtins.dict[x]
except KeyError:
return A(x)
py_object.from_address(id(globals())+tuple.itemsize).value = globols
print(b)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
<__main__.A object at 0x7f6386737d70>
why not hook the builtins namespace lookup instead
since that already happens
mkay
!e ```py
from ctypes import py_object
class A:
def init(self, x):
self.name = x
py_object.from_address(id(builtins.dict)+tuple.itemsize).value = type("missing", (dict,), {"slots": (), "missing": lambda _, x: A(x)})
print(b)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
<__main__.A object at 0x7f1680e83aa0>
yea that works
@lambda x : print(f'${x(input().split()):1.2f}')
def uwo(num):
return sum(map(lambda x : {'quarter' : 0.25,'dime' : 0.10,'penny': 0.01,'nickel' : 0.05,}[x],num))
💀ctypes, the one that I have never touch
Nice
import builtins
import io
import sys
import types
from ctypes import py_object
from forbiddenfruit import curse
from typing import Never, Type, Optional, Any
class MISSING:
pass
class Undefined:
def __init__(self, name: str):
self._name = name
self._value = MISSING()
def __undefined__(self) -> Never:
raise NameError(f'name \'{self._name}\' is undefined\'')
def __del__(self):
if not isinstance(self._value, MISSING):
globals()[self._name] = self._value
__add__ = __undefined__
__radd__ = __undefined__
__mul__ = __undefined__
__rmul__ = __undefined__
__sub__ = __undefined__
__rsub__ = __undefined__
__getitem__ = __undefined__
__setitem__ = __undefined__
__delitem__ = __undefined__
__str__ = __undefined__
__int__ = __undefined__
__bool__ = __undefined__
def writer(self: io.TextIOWrapper, content):
self.write(content)
return self
def reader(self: io.TextIOWrapper, val: Undefined):
name = val._name
content = self.readline()
val._value = content
if name in locals():
locals()[name] = content
elif name in globals():
globals()[name] = content
return content
sys.ENDL = '\n'
class globols(dict):
__slots__ = ()
def __missing__(_, x, builtins=__builtins__) -> Any:
try:
return builtins.__dict__[x]
except KeyError:
return Undefined(x)
py_object.from_address(id(globals())+tuple.__itemsize__).value = globols
curse(io.TextIOWrapper, '__lshift__', writer)
curse(io.TextIOWrapper, '__rshift__', reader)
curse(str, '__lshift__', lambda x, y: x+y)
sys.stdin >> b
sys.stdout << b << sys.ENDL
Thx to ceweal and denball
Hello
and now its much simpler, wouldnt you agree?
plus it works in other modules :3
!e
def local_function():
def square(x):
return x * x
square(25)
def square(x):
return x * x
def global_function():
square(25)
import timeit
n = 10000000
print(timeit.timeit(local_function, number=n), local_function)
print(timeit.timeit(global_function, number=n), global_function)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 1.560410232981667 <function local_function at 0x7f41e7926a20>
002 | 0.8136111649218947 <function global_function at 0x7f41e77294e0>
why local is slower?
I thought it's compiling square just once and save it to local_function.__code__.co_consts and then calling it inside local_function should be faster as it's local name and you don't need to go to globals() dictionary as it will do in global_function
well it does compile the function, but it hasn't made it yet
!e
def local_function():
def square(x):
return x * x
square(25)
print(local_function.__code__.co_consts)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
(None, <code object square at 0x7f6baba113b0, file "/home/main.py", line 2>, 25)
notice how it says "code object"
it only saves the compiled code (since it's guaranteed immutable under normal circumstances)
!e ```py
from dis import dis
def local_f():
def square(x):
return x * x
square(25)
def square(x):
return x * x
def global_f():
square(25)
dis(local_f)
print("---------------------------")
dis(global_f)
ohhh
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 2 0 RESUME 0
002 |
003 | 3 2 LOAD_CONST 1 (<code object square at 0x7ff76f4453b0, file "/home/main.py", line 3>)
004 | 4 MAKE_FUNCTION 0
005 | 6 STORE_FAST 0 (square)
006 |
007 | 5 8 PUSH_NULL
008 | 10 LOAD_FAST 0 (square)
009 | 12 LOAD_CONST 2 (25)
010 | 14 CALL 1
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/HA56KUDCNJLUNDVIYMQCOHXARM
basically it still does square = FunctionType(...) every time
yeah
put it in the defaults
!ti ```py
def square(x):
return x * x
def foo(square=square):
return square(25)
```py
foo()
:white_check_mark: Your 3.12 timeit job has completed with return code 0.
5000000 loops, best of 5: 79.1 nsec per loop
!ti ```py
def square(x):
return x * x
def foo():
return square(25)
```py
foo()
:white_check_mark: Your 3.12 timeit job has completed with return code 0.
5000000 loops, best of 5: 81 nsec per loop
!e ```py
from dis import dis
def square(x):
return x * x
def local_f(square=square):
square(25)
def global_f():
square(25)
dis(local_f)
print("---------------------------")
dis(global_f)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 5 0 RESUME 0
002 |
003 | 6 2 PUSH_NULL
004 | 4 LOAD_FAST 0 (square)
005 | 6 LOAD_CONST 1 (25)
006 | 8 CALL 1
007 | 16 POP_TOP
008 | 18 RETURN_CONST 0 (None)
009 | ---------------------------
010 | 8 0 RESUME 0
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/XLET3H35T5FGLVEW2NA6CLC4JA
the 3 extra instructions are now gone :>
!e
def create_local_function():
def square(x):
return x * x
def local_function():
return square(25)
return local_function
# Create the local function once
local_function = create_local_function()
def square(x):
return x * x
def global_function():
square(25)
import timeit
n = 10000000
print(timeit.timeit(local_function, number=n), local_function)
print(timeit.timeit(global_function, number=n), global_function)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0.8437322149984539 <function create_local_function.<locals>.local_function at 0x7faf415c54e0>
002 | 0.7791375541128218 <function global_function at 0x7faf415c5620>
COPY_FREE_VARS probably contributes to most of the slowdown here
although it seems like global is still faster even with the default-value approach -.-
must be because of the combined PUSH_NULL in LOAD_GLOBAL
was wondering how slow compilation at runtime would be
!e
def compile_at_runtime():
def square(x):
return x * x
local_namespace = {}
exec(compile("def square(x): return x * x", "<string>", "exec"), local_namespace)
local_namespace["square"](25)
def square(x):
return x * x
def global_function():
square(25)
import timeit
n = 10000
print(timeit.timeit(compile_at_runtime, number=n), compile_at_runtime)
print(timeit.timeit(global_function, number=n), global_function)
:warning: Your 3.12 eval job timed out or ran out of memory.
[No output]
ahh, how can I make bot reload the code?
I believe there was some way to do it with reactions
basically results are
0.082665600000837 <function compile_at_runtime at 0x00000216AF6604A0>
0.0005457999995996943 <function global_function at 0x00000216AF8B2660>
click the reaction that the bot adds
although it only automatically adds it after an edit within 10 seconds of the thing being posted
so basically 10 seconds to edit the code
got it, thanks
could a decorator be made so it does this for you automatically for all the local functions given as arguments?
like with code.co_const compile it and pass it as an argument to the function being decorated
but idk how you would rewrite the function's code in runtime easily
could probably be done with some effort though
¿anyone wanna try? because I don't
people have been known to monkey-patch python functions using ast, so that means the function must be python code, which is the case here
here's where I first saw that in practice
other example is PjOrion obfuscation function generates python functions which take code objects, and then access their co_consts, which are also accessed by those code objects themselves (functions like these are specifically crafted for that)
A way of getting the bytecode and modifying it such that It doesnt 'load_const *' and then 'make_func' but call compile it, get It to an object and then get 'load_const' to the made function
If I knew how bytecode is encoded and decoded I could try, but it's just an idea
This hasnt got many usecases though
ah, you mean load_const the function, but instead of make_func then load_name, it would CALL it immediately?
Yeah
Because the decorator loaded the function already compiled it
¿Does that make sense?
hmm, i'll send an example in a few moments, so you tell me is that what you meant
K
!e first, code object and function object are not the same
MAKE_FUNCTION will consume the code object and spit a function object onto the stack, as demonstrated here: ```py
code1 = '''
import types
print(sentinel)
def print_square(x):
return print(x*x)
'''
import types,dis
def modify_bytecode(co, new_bytecode):
return types.CodeType(co.co_argcount, co.co_posonlyargcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags, new_bytecode, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_qualname, co.co_firstlineno, co.co_linetable, co.co_exceptiontable)
co1 = compile(code1, 'filename', 'exec')
bytecode1 = bytearray(co1.co_code)
copy the LOAD_CONST and MAKE_FUNCTION bytecodes
to be the argument to print() call above
notice the function object gets printd
bytecode1[14:16] = bytecode1[26:30]
new_co = modify_bytecode(co1, bytes(bytecode1))
exec(new_co)
print('-'*47)
print(print_square)```
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | <function print_square at 0x7f978892cae0>
002 | -----------------------------------------------
003 | <function print_square at 0x7f978892cae0>
(to keep things short and clean I didn't send disassembly here, but you can just dis.dis(code1) yourself on python 3.12)
!e however I didn't manage to get it working with directly using the function object after MAKE_FUNCTION opcode, as opposed to STORE_NAME the function obj then LOAD_NAME it back, it probably has something to do with the PUSH_NULL
code2 = '''
import types
def print_square(x):
return print(x*x)
sentinel(701)''' # sentinel gets replaced
import types,dis
def modify_bytecode(co, new_bytecode):
return types.CodeType(co.co_argcount, co.co_posonlyargcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags, new_bytecode, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_qualname, co.co_firstlineno, co.co_linetable, co.co_exceptiontable)
co2 = compile(code2, 'filename', 'exec')
bytecode2 = bytearray(co2.co_code)
del bytecode2[14:20]
new_co2 = modify_bytecode(co2, bytes(bytecode2))
print('crashes here')
exec(new_co2)```
:x: Your 3.12 eval job has completed with return code 139 (SIGSEGV).
crashes here
Isnt there a way to check the stack midway through?
There's gotta be a way through that segfault
I get AttributeError: 'code' object has no attribute 'co_qualname'. Did you mean: 'co_filename'
what version of python are you using
an older one, but after removing co_qualname and co_exceptiontable I get this dissasembled version:
2 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (types)
6 STORE_NAME 0 (types)
3 8 LOAD_CONST 2 (<code object print_square at 0x000002F6CD9C4240, file "filename", line 3>)
10 LOAD_CONST 3 ('print_square')
12 MAKE_FUNCTION 0
14 CALL_FUNCTION 1
5 16 POP_TOP
18 LOAD_CONST 1 (None)
20 RETURN_VALUE
Disassembly of <code object print_square at 0x000002F6CD9C4240, file "filename", line 3>:
4 0 LOAD_GLOBAL 0 (print)
2 LOAD_FAST 0 (x)
4 LOAD_FAST 0 (x)
6 BINARY_MULTIPLY
8 CALL_FUNCTION 1
10 RETURN_VALUE
why is it loading the const print_square before the make_function
does it usually do that or is it that some bytecode logic is wrong?
it needs the code object on the stack to make the function
the string.
yes
?
thats the name of the function
K
if I wanted to encode LOAD_CONST (<function something at $ADDR>) into the bytecode, how would that be done?
😛
like create those instructions, and then replace that section of code with the newly made instructions
that point to a function object that has already been created
yk what I mean?
functions arent constant
the code objects are
then how would that be done?
clap it into the function's locals?
def function(x):
def example():pass
print(x*x)
code = function.__code__
instructions = dis.get_instructions(code)
l = list(instructions)
# todo, do some search for this instructions, with dis I saw it was the first instruction, but, yk, search for it better
CODE_EXAMPLE_LOADED = l[0].argval
func = types.FunctionType(CODE_EXAMPLE_LOADED, globals())
func.__name__ = 'example'
# todo, replace those instructions (from instruction 0 to instruction 3) with something to load the object `func` to the variable `example`
after that, create new code object and create new function object with that, dealloc original function and replace it with the new one
that's cursed now that I think 'bout it
and yeah, ik you can pass a name to the types.FunctionType constructor, but last time I checked it didnt work (I didnt check)
I'll think about it tomorrow
get bytecode as bytearray
then
import dis
# tuck a new instruction at index 16
# extra care should be taken if there are JUMP instructions present
bytecode[16:16] = [dis.opmap['LOAD_CONST'], 3]```
and then set that function something at the index 3 of co_consts
and, of course, make a new code object with that
!e @earnest snow ```py
import dis, types
code = '''def print_square(x):
print(x*x)
print_square(555)'''
def modify_bytecode(co, new_bytecode, new_consts):
return types.CodeType(co.co_argcount, co.co_posonlyargcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags, new_bytecode, new_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_qualname, co.co_firstlineno, co.co_linetable, co.co_exceptiontable)
co = compile(code, 'xd', 'exec')
bytecode = bytearray(co.co_code)
bytecode[2:12] = [] # remove actual opcodes up to loading the number 555
bytecode[2:2] = [dis.opmap['LOAD_CONST'], 0]
consts = list(co.co_consts)
consts[0] = types.FunctionType(consts[0], globals())
new_co = modify_bytecode(co, bytes(bytecode), tuple(consts))
dis.dis(new_co)
exec(new_co) # crashes!
:x: Your 3.12 eval job has completed with return code 139 (SIGSEGV).
001 | 0 0 RESUME 0
002 |
003 | 1 2 LOAD_CONST 0 (<function print_square at 0x7f3329819580>)
004 | 4 LOAD_CONST 1 (555)
005 | 6 CALL 1
006 | 14 POP_TOP
007 | 16 RETURN_CONST 2 (None)
why not just co.replace(co_code=new_bytecode, co_consts=new_consts)
there's a lot of uncertainties about replacing a MAKE_FUNCTION with an already-loaded function
a better alternative would be a simple assignment to a sentinel value that gets replaced later
oops :p
silly
!e ```py
import dis, types
code = '''def print_square(x):
print(x*x)
print_square(555)'''
def modify_bytecode(co, new_bytecode, new_consts):
return co.replace(co_code=new_bytecode, co_consts=new_consts)
co = compile(code, 'xd', 'exec')
bytecode = bytearray(co.co_code)
bytecode[2:12] = [] # remove actual opcodes up to loading the number 555
bytecode[2:2] = [dis.opmap['PUSH_NULL'], 0, # needed for CALL mechanism
dis.opmap['LOAD_CONST'], len(co.co_consts)] # use len(consts) because we're appending the function constant later
consts = list(co.co_consts)
consts.append(types.FunctionType(consts[0], globals()))
new_co = modify_bytecode(co, bytes(bytecode), tuple(consts))
dis.dis(new_co)
exec(new_co) # doesn't crash!
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 PUSH_NULL
004 | 4 LOAD_CONST 3 (<function print_square at 0x7faf84911580>)
005 | 6 LOAD_CONST 1 (555)
006 |
007 | 3 8 CALL 1
008 | 16 POP_TOP
009 | 18 RETURN_CONST 2 (None)
010 |
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/CTVTQ7VQJWFPBBUALII6KISTNE
magic!!
I wonder why python compiler just doesn't optimize it by itself since it's clear that this function won't change at runtime
(coming in python 3.13+)

(p.s. they track changes to the function to tell whether or not the code should be re-optimized)
is it me, or python is getting extremely better with every update
hmm.
"extremely" seems a bit over..
it definitely does get better though :>
also function creation doesn't get optimized
only function calls
Does anyone have any code that uses different bitwise operators that I can have a look at?
>>> class x:
... def __or__(self, other): return f'{next(c:=(v for v,k in globals().items() if k in [self, other]))} {next(c)}'
...
>>> Hello = World = x()
>>> Hello | World
'Hello World'
Thank you
so I was living for three years not knowing this exists --------- 
@dusty zodiacthis technically uses bitwise shift operators too
not shift but logic
fyi, CodeType.replace exists
they already know
=v=
i mean- they just knew but like-
they were silly :3
:3
literally me
Please guys answer this:
If I have list say list=[1,2,3] & I need to output a single element each runtime, how do I do it with only a for & if statment? So when I run the code I get 1 only as my outout first only & when I again run the code I get 2 only as my output.
If you mean that each time the python interpreter starts up and runs your module you should get a different number, then I think you'll have to use something outside of Python to do it. The simplest is to write the number to a text file on close and read it on start (maybe treating the file not existing as 1).
If the process can continue running in the background and "running" it means talking to it with some IPC like a pipe, a generator could probably do this for you.
didn't know that reduce is slower just doing a simple loop
!e
products = [
{"name": "Product A", "price": 10},
{"name": "Product B", "price": 20},
{"name": "Product C", "price": 15},
{"name": "Product D", "price": 25},
]
from functools import reduce
def classic_way():
most_expensive = None
max_price = 0
for product in products:
if product["price"] > max_price:
most_expensive = product
max_price = product["price"]
def reduce_way_no_lambda():
def condition_no_lambda(prev, next):
if next["price"] > prev["price"]:
return next
return prev
most_expensive = reduce(condition_no_lambda, products)
import timeit
n = 10000
print(timeit.timeit(classic_way, number=n), classic_way)
print(timeit.timeit(reduce_way_no_lambda, number=n), reduce_way_no_lambda)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0.0025188850704580545 <function classic_way at 0x7fa366a95440>
002 | 0.005534288007766008 <function reduce_way_no_lambda at 0x7fa366a954e0>
you mean making a function and using C code that calls it is slower than just a simple loop
i mean- >->
is it expected?
mhm
🤔
- function is made
- C code incurs function calling overhead for every item
I though one of the points of reduce that #2 will be faster than just doing it yourself
eh.
a simple for loop in python beats almost all contenders that mainly does the job in python.
that also includes just using max() with a key=
def reduce_way_lambda():
most_expensive = reduce(lambda prev, next: max(prev, next, key=lambda x: x["price"]), products)
# 0.0017248999997718784 <function classic_way at 0x000001BE4D5704A0>
# 0.009213199999976496 <function reduce_way_lambda at 0x000001BE4D73D9E0>
# 0.009563799999796174 <function reduce_way_half_lambda at 0x000001BE4D7D5F80>
# 0.0026268999999956577 <function reduce_way_no_max at 0x000001BE4D7D5EE0>
# 0.002238399999896501 <function reduce_way_no_lambda at 0x000001BE4D7D60C0>
okay
i don't think that's how it works
why not just max(products, key=lambda x: x["price"])
yeah, that's probably not the best example for reduce, true
.bm brain hurting code
!e ```py
class foo:
def or(self, other):
first_name = None
second_name = None
for name, obj in globals().items():
if obj == self or obj == other:
if first_name is None:
first_name = name
continue # redundant, for readability only
else:
second_name = name
break
else:
# the break didn't happen (which means we didn't get 2 names)
raise RuntimeError("iterator exhausted")
# return the 2 names joined by a space
return f"{first_name} {second_name}"
Hello = World = foo()
print(Hello | World)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
Hello World
more like it, it all make sense now
thanks
>>> def f(a,b,c): return locals()
...
>>> f(1,2,3)
{'a': 1, 'b': 2, 'c': 3}
Is This A Good Trick or Just esoteric?
seems pretty normal
what is this wow
!d locals
locals()```
Update and return a dictionary representing the current local symbol table. Free variables are returned by [`locals()`](https://docs.python.org/3/library/functions.html#locals) when it is called in function blocks, but not in class blocks. Note that at the module level, [`locals()`](https://docs.python.org/3/library/functions.html#locals) and [`globals()`](https://docs.python.org/3/library/functions.html#globals) are the same dictionary.
Note
The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
i like it
is cute
you want to see something worth this channel?
!e
import types
def _const_mockery(fnc, *consts):
if not isinstance(fnc, types.FunctionType):
return fnc
cfnc = fnc.__code__
r = list(cfnc.co_consts)
for i, rplc in enumerate(consts):
if isinstance(rplc, tuple):
i,rplc = rplc
i += 1
r[i] = rplc
ncfnc = cfnc.replace(co_consts=tuple(r))
return types.FunctionType(ncfnc, globals(), name=fnc.__name__)
def const_mockery_decorator(*consts):
def deco(fnc):
return _const_mockery(fnc, *consts)
return deco
@const_mockery_decorator("you cannot")
def example():
print("I can!")
example()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
you cannot
got a dependencies error for a second
!e
import types
def _const_mockery(fnc, *consts):
if not isinstance(fnc, types.FunctionType):
return fnc
cfnc = fnc.__code__
r = list(cfnc.co_consts)
for i, rplc in enumerate(consts):
if isinstance(rplc, tuple):
i,rplc = rplc
i += 1
r[i] = rplc
ncfnc = cfnc.replace(co_consts=tuple(r))
return types.FunctionType(ncfnc, globals(), name=fnc.__name__)
def const_mockery_decorator(*consts):
def deco(fnc):
return _const_mockery(fnc, *consts)
return deco
@const_mockery_decorator("you cannot Jaja", "=")
def example():
print("can I please?")
print(4 * 30)
example()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | you cannot Jaja
002 | =
it's just = instead of '=' * 30 because python's precalculating the result
!e
const_mockery_decorator=lambda*a:lambda f:(f,setattr(f,"__code__",f.__code__.replace(co_consts=tuple(value if idx==0 or len(a)<idx else a[idx-1] for idx, value in enumerate(f.__code__.co_consts)))))[0]
@const_mockery_decorator("nah", "=")
def example():
print("can i please?")
print(4 * 30)
example()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | nah
002 | =
lmao the parens
lisp incident
that's sad tbh
def _const_mockery(fnc, *consts, ffilter:Optional[Callable] = None, mapping:Optional[Callable] = None):
if not isinstance(fnc, types.FunctionType):
return fnc
if mapping and len(consts):
raise ValueError("map and consts are incompatible")
cfnc = fnc.__code__
r = list(cfnc.co_consts)
assert len(r)
if mapping:
return types.FunctionType(
cfnc.replace(co_consts=tuple(map(mapping, r))),
globals(),
name=fnc.__name__)
ffilter = ffilter or (lambda *v:False)
cindx = 0
for indx, vv in enumerate(r[1:]):
c = ffilter(vv)
if c:
r[indx + 1] = c
continue
if len(consts) < cindx:
v = consts[cindx]
if isinstance(v, tuple):
j, v = v
j = j or cindx
r[j + 1] = v
else:
r[cindx + 1] = v
cindx += 1
ncfnc = cfnc.replace(co_consts=tuple(r))
return types.FunctionType(ncfnc, globals(), name=fnc.__name__)
as far as I'm concerned, this should work ¿right?
like it passes my tests but they're not rigorous
the return value is also affected by this
nice
is there a way to get the original dict of the object using gc? since x is probably referring to it's original __dict__ somehow internally but can't seem to find it in gc.get_referents or gc.get_referrers. Though there is a solution without gc - #1230932562499862578 message but still curious
import gc
def get_true_dict(obj: object) -> dict:
import gc
...
# blocked setattr and __dict__ and __class__
d = {}
class X:
__dict__ = d
__class__ = 42
__setattr__ = lambda *_: 1/0
x = X()
assert x.__dict__ is d
assert get_true_dict(x) is not x.__dict__
d = get_true_dict(x)
d['a'] = 42
assert x.a == 42
d['b'] = 24
assert x.b == 24
print(d)
if len(consts) < cindx:
v = consts[cindx]
huh.
there was conversation about this exact problem a while ago (about a month ago, it feels like)
Yeah the if was wrong, when I get home I'll update the Code and maybe clap that into a class so that It gives you more control of what's goong on
If you mean conversation about retrieving a true dict - I've linked it. Now I was just curious about how it can be done looking through gc references - since a true dict is part of x (as x is using it to retrieve the attributes) there must be some internal python reference from x to a true dict
>>> import gc
>>> class X: ...
...
>>> x = X()
>>> gc.get_referents(x)
[X]
>>> x.a = 1
>>> x.b = 'f'
>>> gc.get_referents(x)
[1, 'f', X]
>>> x.__dict__
{'a': 1, 'b': 'f'}
>>> gc.get_referents(x)
[{'a': 1, 'b': 'f'}, X]
>>> x.__dict__ = {}
>>> gc.get_referents(x)
[{}, X]
>>> x.c = 42
>>> gc.get_referents(x)
[{'c': 42}, X]
i guess there is some lazy dict creation going on
unless you explicitly request x.__dict__, it is not fully created, so it is not present in gc.get_referents(x)
not sure how that even works
Looks like if dict is not created then get_referents is using dict internal contents and just displays it's values
Jelle answered in #internals-and-peps
that's interesting
this feels like a bug lol
there must be some internal python reference from x to a true dict
wrt. that, the above file is useful probably
!e ```py
class DeloFile:
def init(self, file) -> None:
self.file = file
self.__contents = None
self.__parsed = None
self.__vars = {}
def __code(self):
self.__contents = open(self.file, "r").readlines()
def __parse(self):
self.__parsed = [x.strip() for x in self.__contents if x.strip()]
def __main(self):
self.__code()
self.__parse()
for code in self.__parsed:
opcode = code.split()
if opcode[0] == "new":
name = opcode[1]
value = " ".join(opcode[2:])
try:
value = eval(value)
except:
pass
self.__vars[name] = value
def get_data(self):
self.__main()
return self.__vars
:warning: Your 3.12 eval job has completed with return code 0.
[No output]
is there shorter version for get_unique_by_name?
!e
from dataclasses import dataclass
from typing import Iterable
@dataclass
class O: name: str
objects = [O("a"), O("b"), O("a"), O("c"), O("b")]
def get_unique_by_name(l: list[O]) -> Iterable[O]:
d = {}
for o in l: d.setdefault(o.name, o)
return d.values()
#
import inspect
unique = get_unique_by_name(objects)
assert len(unique) == 3
assert set(o.name for o in unique) == {"a", "b", "c"}
code = '\n'.join(inspect.getsource(get_unique_by_name).splitlines()[1:])
golf = len(code)
print(golf, unique)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
72 dict_values([O(name='a'), O(name='b'), O(name='c')])
!e
from dataclasses import dataclass
from typing import Iterable
@dataclass
class O: name: str
objects = [O("a"), O("b"), O("a"), O("c"), O("b")]
get_unique_by_name=lambda l:(d:={},[d.setdefault(o.name,o)for o in l])[0].values()
#
import inspect
unique = get_unique_by_name(objects)
assert len(unique) == 3
assert set(o.name for o in unique) == {"a", "b", "c"}
code = '\n'.join(inspect.getsource(get_unique_by_name).splitlines()
[1:] # well...
)
golf = len(code)
print(golf, unique)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
0 dict_values([O(name='a'), O(name='b'), O(name='c')])
oh, I think we can just use a dict
!e
from dataclasses import dataclass
from typing import Iterable
@dataclass
class O: name: str
objects = [O("a"), O("b"), O("a"), O("c"), O("b")]
def get_unique_by_name(l: list[O]) -> Iterable[O]:
return{o.name:o for o in l}.values()
#
import inspect
unique = get_unique_by_name(objects)
assert len(unique) == 3
assert set(o.name for o in unique) == {"a", "b", "c"}
code = '\n'.join(inspect.getsource(get_unique_by_name).splitlines()[1:])
golf = len(code)
print(golf, unique)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
40 dict_values([O(name='a'), O(name='b'), O(name='c')])
is this the greatest eso-py hello world of all time
beauty is in the eyes of the beholder
is there a way to handle an Exception in one line?
besides contextlib.suppress that allows skipping it
fastest way to get valueerror
heres mine
int("")```
~7.47x faster ```py
raise ValueError
$ python -c "int('')" | time
shell 0.02s user 0.07s system 0% cpu 1:21:06.60 total
children 0.50s user 1.31s system 0% cpu 1:21:06.60 total
Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''
$ python -c "raise ValueError" | time
shell 0.03s user 0.08s system 0% cpu 1:21:15.54 total
children 0.62s user 1.49s system 0% cpu 1:21:15.54 total
Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError``` dont think so
.
you're measuring the entire python startup process
>py -m timeit "try: raise ValueError" "except: pass"
2000000 loops, best of 5: 127 nsec per loop
C:\Users\JerielPC>py -m timeit "try: int('')" "except: pass"
500000 loops, best of 5: 949 nsec per loop
to inlccude the time it takes to parse it
unreliable
also i meant shortest lmao
haha
why would you need to raise ValueError that way?
when you're writing something obscure you usually just need to raise any Exception and 1/0 works for this the best
!e
0.0 is 0
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | /home/main.py:1: SyntaxWarning: "is" with 'float' literal. Did you mean "=="?
002 | 0.0 is 0
omg, python added some syntax warning for this :<
!e
print("Hello World!")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
Hello World!
yes, you can create a class with __enter__ and __exit__ implementations in one line using type which can handle errors for you
try: print(1/int(input()))
except ZeroDivisionError: ...
#suppressing errors using a custom context manager implementation
with type('',(),{'__enter__': lambda self: self, '__exit__': lambda self, *args: isinstance(args[1], ZeroDivisionError)})(): print(1/int(input()))
That's supper cool, I haven't thought about supress actually worked under the hood and that there exception handler integrated to dunder exit
Found a hack to change global variable in that __exit__
!e
a = 25
(lambda: (globals().__setitem__('a', 45), None)[1])()
print(a)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
45
:<
!e
def test():
a = 25
(lambda: (nonlocals().__setitem__('a', 45), None)[1])()
print(a)
test()
:x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 5, in <module>
003 | test()
004 | File "/home/main.py", line 3, in test
005 | (lambda: (nonlocals().__setitem__('a', 45), None)[1])()
006 | File "/home/main.py", line 3, in <lambda>
007 | (lambda: (nonlocals().__setitem__('a', 45), None)[1])()
008 | ^^^^^^^^^
009 | NameError: name 'nonlocals' is not defined. Did you mean: 'locals'?
There seems to be no way to dynamically bind a nonlocal variable in python when variable name is provided from another variable
there is, but its harder
you can get parent frame, and change variable there
there's no easy way to dynamically have a nonlocal variable
at the very least, the variable has to first be declared nonlocal
i've created a class for it but the example looks like this ```py
from nonlocals_proxy import nonlocals
def a():
b = 25
def g():
nonlocal b # still needs this
nonlocals()['b'] *= 2
print(b)
g()
print(b)
a()
woah, interesting!
for some reason I've assumed that you can just add a local with locals()['a'] as you can do with globals but it's not true 😦
!e
globals()["new_global"] = 25
print("new_global in globals()", "new_global" in globals()) # True
print("new_global", new_global) # 25
def test():
locals()["b"] = 25
print("b in locals", "b" in locals())
# NameError: name 'b' is not defined
print("b", b)
test()
:x: Your 3.12 eval job has completed with return code 1.
001 | new_global in globals() True
002 | new_global 25
003 | b in locals True
004 | Traceback (most recent call last):
005 | File "/home/main.py", line 11, in <module>
006 | test()
007 | File "/home/main.py", line 9, in test
008 | print("b", b)
009 | ^
010 | NameError: name 'b' is not defined
ohh, python is being safe
!e
def test_nonlocals():
a = 35
d = locals()
print("original")
print(id(d), d)
def change_nonlocal():
d["a"] = 50
print("inside subfunction")
print(id(d), d)
change_nonlocal()
print("original after subfunction")
print(id(d), d)
b = d["a"]
updated_d = locals()
print("new locals()")
print(id(updated_d), updated_d)
print("original after running locals()")
print(id(d), d)
print(f"a = {a}") # 35
print(f"b = {b}") # 35
test_nonlocals()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | original
002 | 139843347679296 {'a': 35}
003 | inside subfunction
004 | 139843347679296 {'a': 50}
005 | original after subfunction
006 | 139843347679296 {'a': 50}
007 | new locals()
008 | 139843347679296 {'a': 35, 'change_nonlocal': <function test_nonlocals.<locals>.change_nonlocal at 0x7f2fd11214e0>, 'b': 50, 'd': {...}}
009 | original after running locals()
010 | 139843347679296 {'a': 35, 'change_nonlocal': <function test_nonlocals.<locals>.change_nonlocal at 0x7f2fd11214e0>, 'b': 50, 'd': {...}}
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/EWJHTYWEEJ3TEXAUYP2ZX37WAY
class Solution:
@lambda uwu : uwu
def scoreOfString(self, uwu: str) -> int:
uwo,omo=range,ord;return sum(abs(~omo(uwu[owo])-~omo(uwu[owo+1]))for owo in uwo(0,len(uwu)-1))
My current answer to today's
LeetCode. Open to opinions on how to Obfuscate it further.
first thing i'll do is golf it
then try to obfuscate
class Solution:scoreOfString=lambda _,u:sum(abs(ord(x)-ord(y))for x,y in zip(u,u[1:]))
``` golfed
think you lost the bitwise nots
Oh wow didn't know you can just do that with lambda, well the bitwise notes was just to make it more confusing to read.
Other than that yeah it serves no purpose.
class Solution:scoreOfString=lambda _,uwo,omo=zip,owu=ord,:sum(abs(~owu(owo)-~owu(uwu))for owo,uwu in omo(uwo,uwo[1:]))
This runs faster than my previous code lol. It's at
30msand the other one runs at36ms.
guess what this will print
def execute(f):
x = 45
f()
def nonlocals():
x = 25
@execute
def do_nonlocal():
nonlocal x
x += 11
print(x)
nonlocals()
def high_order():
x = 25
def do_nonlocal():
nonlocal x
x += 11
print('do_nonlocal', x)
return do_nonlocal
def execute_and_print(func):
x = 45
func()
print(x)
func = high_order()
execute_and_print(func)
36
do_nonlocal 36
45
has statements == not golfed
This is what it will print.
this is correct
what an absurd definition
less statements == shorter
regardless of character length
How do you propose to golf this code?
..exec()
make it into one expression at least...
exec is cheating and you know it 
..eval()
you chose violence today huh?
Is it technically cheating if there are no witnessses
O.o
here in the world of absolute golfers...
uhm.. idk if I wanna answer that
UwU
exec is occasionally useful in golf
sure but only when there's not a shorter alternative
t=eval("int(input()),"*2)
t=*map(int,open().split()),
not as a way to technically make your code a single expression even though it's hella statements lol
this is not what I meant, and I feel like you know that
eh? there's other meanings?
"a golf with multiple statements is cheating" ->
"eval" (implying that you can use eval to make your multiple statements into an expression even though it's killing the point) ->
"you wouldn't use eval in a golf" (you [ceweal] wouldn't use it as a way to turn your code into a single expression)
hm.
maybe speak clearer next time =w=

Why statements are bad in golf? I mean a newline is just 1 character 😄
in some types of golfers
or some variations of golfing
code must be one statement/one expression only
it produces more interesting code when you make it into a single statement/expression, and you have reduce the code down in a way that a lot of people don't even know how to do, where using semi colons can be done by literally anyone who knows a little python to turn a program into one line
I think it depends on the golfer and personal preference.
import zen_of_golf
Hahaha
"Golf it."
GolfIt
semicolon usage is a common thing in golfing
at the very least, absolute golfing
It seems sometimes (besides the cases when we're inside some indentation block) a semicolon doesn't really help in golfing since it's still just 1 character as a newline and it only makes things appear more obfuscated
class Solution((OwO:=(iwt:=(umu:=sum)((IvI:=zip)((owu:=range)((IwT:=int)()))))or[qwq:=5,pwq:=(uvu:=eval)(QwQ:=f"{qwq}*-{qwq}")-(pwp:=QwQ.count(chr(qwq+b'0'[0]))),pwq//(owo:=qwq-pwp)*~owo,qwq+iwt,-uvu(TwT:="(ovo:=%u%%u)"%-~-IwT()%iwt)-owo,*[owo*(-pwq-ovo*pwp),pwq+ovo,qwp:=~qwq][::~iwt],-qwp,qwp,pwp,pwp*~-~iwt]).__class__.__mro__[qwp+qwq]):
@(lambda _w_:lambda uwu:_w_.__ior__({f'{(c:="%c"*(bwd:=pwp-qwp))}t{c[:bwd>>pwp+~IwT()]*pwp}'%(*[x3+umu(OwO[:-~iwi])for iwi,x3 in IvI(*[uvu('b%r'%uwu.__name__),owu(owo*qwq**qwq)][::~iwt])],):uwu}))(locals())
def nya__OwOhehe(_,uwo):uwo=uvu('b%r'%uwo);return umu(abs(Ywy-ywY)for Ywy,ywY in IvI(uwo,uwo[qwp//-qwq:]))
what i just sent is about average runtime btw
print(Gramaticallyᅠcorrectᅠvariableᅠnameᱹ:='Hello World')
!e
print(Gramaticallyᅠcorrectᅠvariableᅠnameᱹ:='Hello World')
print(globals())
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | Hello World
002 | {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f117a384d70>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/main.py', '__cached__': None, 'Gramaticallyᅠcorrectᅠvariableᅠnameᱹ': 'Hello World'}
looks like a programming crime
Look what I have done with Python https://youtu.be/cw7qHNntBas?si=GJBrYyhuxUVxbWvF, its a binary waterfall with the famous emulator MelonDS for Windows
This video will install melonDS (a Nintendo DS emulator) into your brain, this is compatible for all brain softwares. No need to do anything, just watch and listen to all those noises and it will successfully install
END OF DESCRIPTION
SOCIAL MEDIA
DISCORD: https://discord.gg/J4xqCPQzDz
FACEBOOK: https://www.facebook.com/macosfangamer
TWITTER ...
wow a whole 16 minutes of intolerable screeching? for me? 
is there way to make it work?
def same_address(a, b):
return a is b
def test():
a = 25
def do_nonlocal():
nonlocal a
a = 50
do_nonlocal()
assert same_address(a, do_nonlocal.__closure__[0].cell_contents)
b = 50
assert not same_address(a, b)
assert not same_address(a, 50)
test()
you mean no constant caching?
i mean to compare two int variable if they are actually the same
in this example do_nonlocal.__closure__[0].cell_contents actually points to a
and changing do_nonlocal.__closure__[0].cell_contents will change a and vice versa
and I'm curious if it's possible to check if they are the same
besides changing them
same_address() checks that two objects are the same, not two variables
you mean they're different based on the location in which they're assigned?
that's hard to do
maybe impossible
I mean a is pointing to some address xxxx in memory and do_nonlocal.__closure__[0].cell_contents is pointing to the same address and curious if there is a way to get that address to see if two variables are actually pointing to the same address.
but checking id() doesn't work to get this address for ints and other literals as i,j = 5, 5; assert i is j; assert id(i) == id(j)
b is pointing to the same address as well
what do you mean by "same address"?
a is b works perfectly, it tells you exactly what you want: are two objects located at the same address or not
I mean this behaviour.
!e
def test():
a = 25
def do_nonlocal():
nonlocal a
a = 50
do_nonlocal()
print('after call', a, do_nonlocal.__closure__[0].cell_contents)
a = 77
print('a value changed', a, do_nonlocal.__closure__[0].cell_contents)
do_nonlocal.__closure__[0].cell_contents = 99
print('closure value changed', a, do_nonlocal.__closure__[0].cell_contents)
test()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | after call 50 50
002 | a value changed 77 77
003 | closure value changed 99 99
it's like a and do_nonlocal.__closure__[0].cell_contents are pointers and they're pointing to the same *container.
and to assert they're pointing to the same *container we'll need to now &container
but when we do id(a) or id(do_nonlocal.__closure__[0].cell_contents) it's more like we're getting the container instead (address of the value in the container instead of the container address).
if this makes sense 😄
I mean
ais pointing to some addressxxxxin memory anddo_nonlocal.__closure__[0].cell_contentsis pointing to the same address and curious if there is a way to get that address to see if two variables are actually pointing to the same address
???
you say they are pointing to the same address, and then you want to check if they point to the same address?
they are pointing to the same PyObject
I was just curious if it's possible to get that address
id
or ctypes
id is easier
id won't work here
wdym
!e
def test():
a = 25
def do_nonlocal():
nonlocal a
a = 50
do_nonlocal()
print('after call', a, do_nonlocal.__closure__[0].cell_contents)
a = 77
print('a value changed', a, do_nonlocal.__closure__[0].cell_contents)
do_nonlocal.__closure__[0].cell_contents = 99
print('closure value changed', a, do_nonlocal.__closure__[0].cell_contents)
b = 99
print(id(a), id(do_nonlocal.__closure__[0].cell_contents), id(99), id(b))
test()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | after call 50 50
002 | a value changed 77 77
003 | closure value changed 99 99
004 | 140166848170152 140166848170152 140166848170152 140166848170152
all 4 pointing to the same address
though only a and do_nonlocal.__closure__[0].cell_contents are actually correlate
that is because they are all the same object
well yes obviously different variables wont be reassigned when you reassign one variable
but thats not relevant because you dont want the id of b, nor do you want the id of some arbitrary const; you want the id of a
i genuinely have no clue why you think id doesnt work here lol
okay, I'll try to illustrate it with c-code - https://pastebin.com/zXDUbZye
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
can i ask you a question?
have you read through any of the CPython source?
i asked because it doesnt really show the behaviour
when we change a it also change cell_contents and vice versa but id appears to be the same for both of them and also b
id of the container?
which container?
this is because they all point to the same object
you can change cell_contents, then look at a and if it changed as well, then they are storing pointer in the same location
but if changing a changes cell_contents it means they do share some container that then points to the object
yes, this one makes sense, the only way I could think of it
everything else is probably hidden somewhere deep in memory
another way is to look at the code with your eyes
again, do_nonlocal.__closure__[0]
that's the primary cell container
every other container level is basically the equivalent of internal locals()
the one in the closure has an extra pointer, yes
its not shared though
a is a PyObject*
directly
pretty much
you mean do_nonlocal.__closure__[0] is just points to Pyobject* a?
a dynamically loads do_nonlocal.__closure__[0].cell_contents everytime it's mentioned
inside do_nonlocal yes
!e ```py
from dis import dis
dis(r"""
def test():
a = 25
def do_nonlocal():
nonlocal a
print(a)
""")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 2 2 LOAD_CONST 0 (<code object test at 0x7fe932151b50, file "<dis>", line 2>)
004 | 4 MAKE_FUNCTION 0
005 | 6 STORE_NAME 0 (test)
006 | 8 RETURN_CONST 1 (None)
007 |
008 | Disassembly of <code object test at 0x7fe932151b50, file "<dis>", line 2>:
009 | 0 MAKE_CELL 1 (a)
010 |
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/DHVYQLSHYN6JEWF4KHEPBLEPVI
Python/bytecodes.c lines 1613 to 1620
inst(LOAD_DEREF, ( -- value)) {
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
value = PyCell_GetRef(cell);
if (value == NULL) {
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
ERROR_IF(true, error);
}
}```
they mean the a outside of do_nonlocal i believe
ohh, i see it creates a cell with MAKE_CELL and both test and do_nonlocal use that cell to get the value of a using LOAD_DEREF
!e ```py
from dis import dis
dis(r"""
def test():
a = 25
def do_nonlocal():
nonlocal a
print(a)
print(a)
""")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 2 2 LOAD_CONST 0 (<code object test at 0x7fe852a261f0, file "<dis>", line 2>)
004 | 4 MAKE_FUNCTION 0
005 | 6 STORE_NAME 0 (test)
006 | 8 RETURN_CONST 1 (None)
007 |
008 | Disassembly of <code object test at 0x7fe852a261f0, file "<dis>", line 2>:
009 | 0 MAKE_CELL 1 (a)
010 |
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/PYB7DLUOP7JWQK3A67NPBAZ2TY
yea
yes
so, basically there is just one pyobject * and therefore there is no need to have common container between them
yes
huh?
I just thought before that a and cell_content are using two separate pyobjects and therefore there would be some common container between them, so they would be able to share the same value
well there is a common container
and only one object inside that container
unless you include the container which is an object itself
!e ```py
import random
group_1 = ["`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "=", "+", "[", "]", "{", "}", "\", "|", ";", ":", "'", """, ",", ".", "<", ">", "/", "?"]
group_2 = [str(x) for x in range(0, 9)]
group_3 = ["A", "E", "I", "O", "U", "Y"]
group_4 = ["B", "C", "D", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "V", "W", "X", "Z"]
def encode(message):
split = [x for x in message]
split = [x.upper() for x in split]
for index, char in enumerate(split):
print(split)
if char in group_1:
split[index] = "SC" + str(group_1.index(char)).zfill(2)
elif char in group_2:
split[index] = "N" + char
elif char in group_3:
split[index] = "V" + char
elif char in group_4:
split[index] = "C" + char
elif char == " ":
split[index] = "S"
return ''.join(split)
def decode(encoded_message):
decoded_message = ""
index = 0
while index < len(encoded_message):
if encoded_message[index:index+2] == "SC":
char_index = int(encoded_message[index+2:index+4])
decoded_message += group_1[char_index]
index += 4
elif encoded_message[index] == "N":
decoded_message += encoded_message[index+1]
index += 2
elif encoded_message[index] == "V":
decoded_message += encoded_message[index+1]
index += 2
elif encoded_message[index] == "C":
decoded_message += encoded_message[index+1]
index += 2
elif encoded_message[index:index+2] == "S":
decoded_message += " "
index += 2
return decoded_message
message = """Hit the showers!"""
encoded_result = encode(message)
decoded_result = decode(encoded_result)
print(f"original message: {message}")
print(f"encoded message: {encoded_result}")
print(f"decoded message: {decoded_result}")
!e
B=getattr
A=bytes
_______='BQAAAAEAAABzDAAAAPADAQEB2QAFgGSFC3IDAAAA'
_____='ZQBkAKsBAAAAAAAAAQB5ASkCegI6M04pAdoFcHJp'
____='LjNNNNNNNNNNNNNNNNZNNNNNNNNN8kDNNNPKNNVN'
______='y5TZsVHZv1GPIovPn5WayR3c8gg+AAAAAMPApSnb'
__import__(B(__import__(A([98,97,115,101,54,52]).decode()),A([98,54,52,100,101,99,111,100,101]).decode())(A([89,110,86,112,98,72,82,112,98,110,77,61])).decode()).exec(__import__(B(__import__(A([98,97,115,101,54,52]).decode()),A([98,54,52,100,101,99,111,100,101]).decode())(A([98,87,70,121,99,50,104,104,98,65,61,61])).decode()).loads(__import__(B(__import__(A([98,97,115,101,54,52]).decode()),A([98,54,52,100,101,99,111,100,101]).decode())(A([89,109,70,122,90,84,89,48])).decode()).b64decode(__import__(B(__import__(A([98,97,115,101,54,52]).decode()),A([98,54,52,100,101,99,111,100,101]).decode())(A([89,50,57,107,90,87,78,122])).decode()).decode(____,__import__(B(__import__(A([98,97,115,101,54,52]).decode()),A([98,54,52,100,101,99,111,100,101]).decode())(A([89,109,70,122,90,84,89,48])).decode()).b64decode('cm90MTM=').decode())+_____+______[::-1]+_______)))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
:3
i love goofing off with this
!e
import base64, lzma; exec(compile(lzma.decompress(base64.b64decode(b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4BcyBNxdAC/rhAeiEv8hIKAMtZdqenDYr68Xwx03OtBiFWoJJh7Sb1x5Xyg0jzZRen5Co2eix4DvAxFW3QXe11T1eFeYbCxaIhJaua8r0p4Fd0QeKNSUVCftwj3NP56jbxsBDZ3fnkChRBtFMM0kF+Xzc6cdlfErf4Xrc9gwR8aR3TtB5anYtz5cjIGTww0PJKnC6CPPbuW44NcgM5I6wTdTDuj7k6JNVZ4cOCZCDOJLifXXkMC0dG7ZlDJLc20p4vjyeY/8zT7BFFCohFOjIYUn0O/p+8f4CJdrcDv2OG7p0EWLtmQdpsbNwVqdvlAn0z8JYGyWyWB0w/7hXADviN0l3ytL+74vWGmMg6miFI9VZhlWWGKcYFSvmZnUTYgJcQaEVARQAKRazmDQ8OjYYYVAiHAL3jNk+Oa+v4LWUJfQY70TIZ2ewttLegWKDi9En6i/hRzdjMnXAQddMtB3clkVDP26ZpQyXSZAh/g8XMZ6dUlDdfyHX6HUc6qnvYrTQirf/lquAdOkL4Kjh156rwZpyLLM+DY0XujDZEF3NcO+QrMhESczueOFcaKso2mVi2fhNI7Kon+h7+DQfB0XEr2Wc/HxMnFtKJcVm8JQisH6zSadDAxGyzJ/Agqr3QvP2kCp7IaFOyR2jmYvowPEFtH7yLQzOnWX7osAaZzfkg+R4FufBQqaWy+fExzXaqa2AZermbfMwB/NnwXi/khuEYeHnbnbCxCZJuzBz2V8xIFzIPwwd4s1OeMq17981PzSprJEsj6PZq06fNFmpdpt1ohPfCFCFmh93+eIVbCKbt0uQjQSWdfu1t/HG5seMYN7rXxUNF43JCeiVrneaqXoSUA1tmfkyVN8TKCL8pX297KiXF7ZRyOhHnhdGLesQqwuZC36oGBZnwCktARkEZm6Ha69sAOMZ3VRUNvIHdePE2F1E6uWnIyYc2ctzuqvf/LzYV3NAx8SW/N42pQVHNm3ESTlVnuMTWB2klkbGmzy05SLFXgvWH1hKupDbTX4buqrC6BmYypg6/y7XuRiqtJ0XMyaSMxcwAV0qaKkpH6EXCQvlae88slkh5u8reIhEq6oWFwxYzQlb5Q11frhe9nQOs9F51aZhBFEPLx885lpNTE+AhzBZEFnFpGGmYWYZu+KxD8KutfRYqi1GrOiYIJl9wLZrw1EQT9yJdu6e6ufH+lzNSaD2WRFMkuEkmfYVUwzBmbvyBI+0YrGmnSbAvLHiSKQnONqVkqAirzGWxP7XJ8C/5Gx+ZAtMl9nW1KIitFe1tVcsBBAa8eFBmZXCzV4DSQFg3VMMOIrY7pbNsx4/xmxHdh4PVxwkCbOIjsoiMjw7XfiafgoC8nvTLwHTXRHXs2pGo5wiTTgoQo0pUOc/D/6cOpWccj7rkfoMGcWXK3RbJwr4hAIYOAJqdjsBAAM2mIuyb3hAh4fYVQZn1Z1yOSAnQB/sdqUjXXpSGYbc4TcL3bFQYvl4rm/tzg/TZGj0pnRxjXhyFuizUq7/RaLBe3lLwSLSPQ8yi6VeAAmeRPRGTyMvRyovE8UdQeYS7NM2z+8XIf0FaAYv/Ru66CM0Gm6BoTlBG271LwiCdml3MmnDi0MMU4kHfVfjHF3CwbIy5UyH0CZPfD0OycQ/s/OQ9qmlePI4Y2SWbUyTwrHMNJSiQdDAGLhmqlSweoSAAH4CbMuAABGp5AKscRn+wIAAAAABFla')), "<string>", "exec"))
LOL
i did it wrong
:white_check_mark: Your 3.12 eval job has completed with return code 0.
:3
someone tell me the exact code that this runs. and how long it takes you to get it
!e
hello = 25
print(f'{hello=}'.split('=', 1)[0])
:white_check_mark: Your 3.12 eval job has completed with return code 0.
hello
what is "exact", exactly
because a lot of redundant operations can be removed
import base64, lzma
import os
_L0 = b"base64"
_L1 = b"b64decode"
A = eval
B = getattr
C = __import__
D = bytes
E = lambda string: compile(string, "<string>", "exec")
G = r"""
import marshal, codecs
A = 'LjNNNNNNNNNNNNNNNNLNNNNNNNNN8mbNNNPKNNVNMDOxNNVNMDSxNnfONNNNNNNNntDNNNNN'
B = '8gg++cmbpJHdzxDC6DAAAAw8AkqcyVGZ0NnBa/1X0J3bw1Waf9lCaTnbpJHcFo9Ap4EZuV2A'
C = 'AAAAAAAAAAAAAAAAAABkAqwDqwMAAAAAAAABAHkEKQV6Ajoz2gNzeXN6AgkKKQLaBGZpbGXa'
D = 'bW9kdWxlPnIKAAAAAQAAAHMcAAAA8AMBAQHZAAWAZJEamEXTESLXESnRESmoZtYANXIIAAAA'
exec(marshal.loads(base64.b64decode(codecs.decode(A, base64.b64decode('cm90MTM=').decode()) + C + B[::-1] + D)))
"""
try:
exec(E(G))
os._exit(0)
except lzma.LZMAError:
...
import os
G = r"""
print(":3", file=__import__("sys").stderr, end="\t\n")
"""
exec(G)
os._exit(0)
import os
print(":3", file=__import__("sys").stderr, end="\t\n")
os._exit(0)
that's about uhh 24 minutes to decode
(all the imports were made into statements for "convenience")
pretty impressive
tbh
the code behind it is uh
something,
5 secconds
>>> import lzma
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/redacted/.pyenv/versions/3.12.1/lib/python3.12/lzma.py", line 27, in <module>
from _lzma import *
ModuleNotFoundError: No module named '_lzma'``` \:3
well
first part of how it works
O,N,L,J,I,H,G,F,C='exec','<string>',False,'eval','bytes','getattr','__import__',list,True
import random as P,string,base64 as E,codecs as Q,argparse as R,os as A,sys
def encryptstring(string,config={},func=L):
K=string;A=config;N=F(b'base64');O=F(b'b64decode');__import__=A.get(G,G);getattr=A.get(H,H);bytes=A.get(I,I);eval=A.get(J,J)
if not func:return f"{getattr}({__import__}({bytes}({N}).decode()), {bytes}({O}).decode())({bytes}({F(E.b64encode(K.encode()))})).decode()"
else:
B=K.split('.');P=encryptstring(B[0],A);B=F(map(lambda x:encryptstring(x,A,L),B[1:]));C=''
for(Q,M)in enumerate(B):
if Q==0:C=f"{getattr}({eval}({P}), {M})"
else:C=f"{getattr}({C}, {M})"
return C
print(f"exec({encryptstring('print("?")')})")
gl decoding
!e ```py
def f():
try:
print(end='.')
f()
except:
print(end='!')
f()
finally:
print(end='@')
f()
f()
:x: Your 3.12 eval job timed out or ran out of memory.
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................!
... (truncated - too long)
Full output: https://paste.pythondiscord.com/3M2UTJJQEUHC2E23QR2JWP5YKQ
well, beginning of it is boring
after 1k chars it becomes interesting
it is also becomes slower and slower over time, and takes up more and more memory
after i fix my name lookups i'm gonna tackle this
lol
Well, I might have got something better
!e
for i in range(1,99):
for(e)in(a:=[[]for()in[()]*i]):e+=a
print(i, e)
:x: Your 3.12 eval job has completed with return code 143 (SIGTERM).
001 | 1 [[...]]
002 | 2 [[[...], [...]], [...]]
003 | 3 [[[...], [[...], [...], [...]], [...]], [[[...], [...], [...]], [...], [...]], [...]]
004 | 4 [[[...], [[...], [...], [[...], [...], [...], [...]], [...]], [[...], [[...], [...], [...], [...]], [...], [...]], [...]], [[[...], [...], [[...], [...], [...], [...]], [...]], [...], [[[...], [...], [...], [...]], [...], [...], [...]], [...]], [[[...], [[...], [...], [...], [...]], [...], [...]], [[[...], [...], [...], [...]], [...], [...], [...]], [...], [...]], [...]]
005 | 5 [[[...], [[...], [...], [[...], [...], [...], [[...], [...], [...], [...], [...]], [...]], [[...], [...], [[...], [...], [...], [...], [...]], [...], [...]], [...]], [[...], [[...], [...], [...], [[...], [...], [...], [...], [...]], [...]], [...], [[...], [[...], [...], [...], [...], [...]], [...], [...], [...]], [...]], [[...], [[...], [...], [[...], [...], [...], [...], [...]], [...], [...]], [[...], [[...], [...], [...], [...], [...]], [...], [...], [...]], [..
... (truncated - too long)
Full output: too long to upload
:x: Your 3.12 eval job timed out or ran out of memory.
001 | 1
002 | 2
003 | 3
004 | 4
005 | 5
006 | 6
007 | 7
008 | 8
009 | 9
Each i make it exponentially harder to represent
!eval
import time
for i in range(1,99):
gen_start = time.perf_counter()
for(e)in(a:=[[]for()in[()]*i]):e+=a
gen_end = time.perf_counter()
repr(e)
repr_end = time.perf_counter()
print(f"{i} gen:{gen_end-gen_start} repr:{repr_end-gen_end}")
lol, this more on memory issue here
!eval
import time
for i in range(1,99):
gen_start = time.perf_counter()
for(e)in(a:=[[]for()in[()]*i]):e+=a
gen_end = time.perf_counter()
d = repr(e)
repr_end = time.perf_counter()
size = len(d)
print(f"{i} gen:{gen_end-gen_start} repr:{repr_end-gen_end} resolved:{size}")
:x: Your 3.12 eval job timed out or ran out of memory.
001 | 1 gen:2.7799978852272034e-06 repr:1.0979827493429184e-05 resolved:7
002 | 2 gen:2.7599744498729706e-06 repr:2.6598572731018066e-06 resolved:23
003 | 3 gen:1.5601981431245804e-06 repr:2.9900111258029938e-06 resolved:85
004 | 4 gen:1.2700911611318588e-06 repr:8.180039003491402e-06 resolved:373
005 | 5 gen:1.500127837061882e-06 repr:3.31709161400795e-05 resolved:1955
006 | 6 gen:1.6700942069292068e-06 repr:0.0001745428889989853 resolved:12067
007 | 7 gen:1.8300488591194153e-06 repr:0.0012010619975626469 resolved:86113
008 | 8 gen:2.6999041438102722e-06 repr:0.011023266008123755 resolved:698705
009 | 9 gen:4.2798928916454315e-06 repr:0.08726717694662511 resolved:6356863
1 gen:4.842004273086786e-06 repr:3.0520022846758366e-06 resolved:7
2 gen:3.905995981767774e-06 repr:3.335997462272644e-06 resolved:23
3 gen:5.086010787636042e-06 repr:9.846989996731281e-06 resolved:85
4 gen:3.905995981767774e-06 repr:2.1321990061551332e-05 resolved:373
5 gen:0.00031872501131147146 repr:0.00010506197577342391 resolved:1955
6 gen:5.6150020100176334e-06 repr:0.0005939529801253229 resolved:12067
7 gen:5.616020644083619e-06 repr:0.002996092982357368 resolved:86113
8 gen:5.817972123622894e-06 repr:0.019604859000537544 resolved:698705
9 gen:1.102700480259955e-05 repr:0.1897019449970685 resolved:6356863
10 gen:1.794402487576008e-05 repr:1.9098649919906165 resolved:64116655
11 gen:1.2329983292147517e-05 repr:21.2753957209934 resolved:710215277
Killed
[Program finished]
From my phone (if you want a more comprehensive info
def ᅠ(ᅠ):
ᅠᅠ,ᅠᅠᅠ=(ᅠ!=ᅠ)+(ᅠ!=ᅠ),(ᅠ==ᅠ)+(ᅠ!=ᅠ)
while ᅠ:
ᅠᅠ,ᅠᅠᅠ=ᅠᅠᅠ,ᅠᅠ+ᅠᅠᅠ
ᅠ-=ᅠ==ᅠ
return ᅠᅠ
can you guess what it does?
fibonacci sequence?
a good 2 minutes of looking at the assignments and thinking "hmm, this looks familiar"
...it does calculate the fibonacci sequence to a point but returns 0
oh
i forgot to select one character
for each expression find such x (or produce x with some code, or replace x with some expression), so that expression evaluates to True: ```py
isinstance(x, int) is x
type(x) is x.class is x is x()
x==42 and x!=42
x==42 and not (x==42)
x is not x
object() is x
id(x) % 997 == 42
hasattr(x, 'x') and not hasattr(x, 'x')
dir(x) == []
len(x) is x
id(x) is x
type(x) is str and eval(x, {}, {}) == x
type(x) is str and (t:=eval(x, {}, {})) == x and type(t) is str # same as previous one, but more constrained :)
type(x) is str and eval(x42, {}, {}) == 42
type(x) is str and eval(x42, {}, {}) == 69
rules are not very strict, the only goal is to have fun
i guess it would be a good idea to hide your answers behind a spoiler
||```py
x = True
isinstance(x, int) is x
from ctypes import py_object
class x(type):
new = lambda *a: x
init = lambda *a: None
py_object.from_address(id(x)+tuple.itemsize).value = x
type(x) is x.class is x is x()
@type.call
class x:
eq = ne = lambda *a: True
x==42 and x!=42
@type.call
class x:
def eq(_, a, b=[]):
if t := a not in b: b.append(a)
return t
x==42 and not (x==42)
x is not x
[] is not []
object = lambda: x
x = ...
object() is x
t = []
while id(x := []) % 997 != 42: t.append(x)
id(x) % 997 == 42
@type.call
class x:
def getattribute(s, a, see=[]):
if a not in see:
see.append(a)
else:
raise AttributeError
hasattr(x, 'x') and not hasattr(x, 'x')
@type.call
class x:
dir = lambda *a: []
dir(x) == []
from ctypes import py_object
class x(int):
len = lambda s: s
py_object.from_address(id(0)+tuple.itemsize).value = x
x = 0
len(x) is x
oh no, you finally answered 💀
there are more elegant solutions to type(x) is x.__class__ is x is x() and len(x) is x (that do not involve ctypes)
:)
and you kinda cheated in object() is x by shadowing object
i believe there is a way || to replace x with some expression||
haven't checked yet though, not near my pc currently
you lieddjdd >へ<
rules ar strictt.. =-=
i hope you had fun, and that's all that matters
i actually forgot that ||__dir__|| exist, i expected a lot more cursed solution (not sure that the thing i imagined is possible without ctypes though)
added a couple more things
Anyone solved this tho
it prints :3
and also this ```py
<stdin>:1: DeprecationWarning: Bitwise inversion '~' on bool is deprecated. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
!e
exec("a = (1,(1,2))")
b = (1,(1,2))
print(a is b)
a = (1,(1,2))
print(a is b)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | False
002 | True
they're both cached in a co_consts but the one created in the exec() is different from the one created in the top level code
interesting that it's different if some element of the tuple is mutable
!e
c = [1,2,3]
exec("a = (1,c)")
b = (1,c)
print(a is b)
a = (1,c)
print(a is b)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | False
002 | False
yes because they're not cached as constants anymore
i was wrong actually, my idea didnt work
i thought of this: ||```py
class X(int):
len = lambda s: s
x = X()
assert len(x) is x
but apparently ||`len()` converts int subclasses to ints||
wth
you just found that out now... =v=
BrainPython has some bugs unfortunately
Ye, I am completely ignoring this btw
my motivation is on the verge of extinction
sklil issue
@pallid flare donate cereal some motivation so he can complete python 4
i have none left
im trying to regenerate my motivation
and failing
for months
so gl
try eating ice cream :3
if you can
i wont let that happen so no
python 3 shold continue till infinity
what the duck
you don't even use python anymore
your job is to motivate him
rust better.
says the roblox dev
typescript better 🙃
says the roblox dev
i use typescript for roblox dev
doesn't matter its roblox
c & c++ > rust :3
and python is pretty much c if you think about it
i was joking, i dont use rust or know it well
rust syntax is true physcological horror
the syntax is okay at best
no
thats another thing comes after syntax
I wonder how much zig is used
its bad
then why did you say no
you said that syntax is ok
whatever you guys say roblox lua is the best language
i said it was okay at best
what does that mean
that means that the syntax is ≤ okay
is it more annoying then TS?
then you said it was not ≤ okay, which would mean it would have to be good
I haven't tried both but have read code of them
never used TS, never will
same
i dislike JS a lot
I do dislike js but I am not gonna use ts either its too much work
I got a IDE I will use JS with type checking
I even use python with basic type checking
type checking is kinda annoying
:(
this is the same code from before or my eyes are deceiving nme
OHMYGODISIT??
Nope (probably not
Cuz I wrote and compile it new
!e the regex part could have probably be done better but I hope you're satisfied ```py
import ast, re, zlib
from operator import *
code = zlib.decompress(b'x\x9c\xe5VI\x0e\xc3 \x0c|M\x84\r\xca\x0b\x02o\xb1\xaa\xaa\xb7\x9e{\xec\xdb\x0b\xad\xd4Bdg\x01\xa7\x8d\xd2\b%a\x18{f"(\n\xa7\xeb@\x14\xcc\xd9\xc4\x1b\x05\x02\x00\xd3\x19G\x84],\xfb;\x00z@t\x9f\xd2\xfbw\x89h\xad\xf4\x82]\xebZ \xd3\xe5rz\xdcg|\x19\xe9\xcco\xbc\x19\xcf\x160=R\x96\x1f\x98\xf8\xdc\x95-\r\x04\xd1 \xd1i\xa16A\xda=\xf7T\xdbHjUS\xf9\xdfMi\x7fq\xc5\xc4jL\xae0\x9f \x89\x10\xe3>\xc3\xefE\xcc\x05\x86\xd6W\r\xd6\x81\x1bO\xcb\xe4\xde\x85NJ\x02\xd5\xc3\x195\xb5\x0eg\xe9?\x8fI\xd6<\x1b\x81\xcc!\xc6\xf1\x02\x9f\xf6\xfb_\xe6\xa0"\x06:Zg!\xac\x9c\xa3\x1e\x93\xaa\xb0\xf0\xf6o\xd3DO\E\x99\x8a\xf0\xec\xe3H\xf8u\xe97\xb7\xa0\xc2QHS\xf2\x07\xfe\xcd\xb2 ').decode()
code = ast.unparse(ast.parse(code)).replace('-~(() < ())', '1').replace('', 'var1').replace(" = 'c'\n", '').replace('_', '"c"')
operations = {
ast.LShift: lshift,
ast.Pow: pow,
ast.Add: add,
ast.Mult: mul,
ast.Sub: sub,
ast.Mod: mod
}
class Transformer(ast.NodeTransformer):
def visit_BinOp(self, node):
self.generic_visit(node)
if isinstance(node.left, ast.Constant) and isinstance(node.right, ast.Constant):
return ast.copy_location(
ast.Constant(value=operations[type(node.op)](node.left.value, node.right.value)),
node
)
return node
Transformer().visit(tree := ast.parse(code))
code = ast.unparse(tree)
code = re.sub('var1(\d*)', lambda t: f'"{chr(int(t.group()[5:-1]))}"', code)
Transformer().visit(tree := ast.parse(code))
code = ast.unparse(tree)
print(code)```
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | /home/main.py:26: SyntaxWarning: invalid escape sequence '\('
002 | code = re.sub('var1\(\d*\)', lambda t: f'"{chr(int(t.group()[5:-1]))}"', code)
003 | _ = eval
004 | var1 = _('chr')
005 | _('exec')("print(':3')")
Nice
The actual code is just inside line 5 according to evaluation btw lul
Other was the payload
*bootstrap
it is actually
idk if this is the right place but, is there some way to convince hypothesis to do coverage guided fuzzing?
like if i keep a set of "seen" pcs as coverage, will target(len(coverage - seen_pcs_this_run)) essentially guide the fuzzer?
class StateVariable:
def __init__(self, category, name, default):
self.__state__ = {
"category": category,
"name": name,
"default": default
}
def __str__(self):
return self.__state__["default"]
def add_state(category, name, default):
return StateVariable(category, name, default)
if __name__ == "__main__":
# Example usage
x = add_state(category="main", name="ip address", default="127.0.0.1")
print(x) # Output: 127.0.0.1
print(x.__state__) # Output: {'category': 'main', 'name': 'ip address', 'default': '127.0.0.1'}
print(type(x)) # Output: <class '__main__.StateVariable'>
x = "0.0.0.0"
print(type(x)) # Output: <class 'str'>
is there a way to override the functionallty of x = "..."
and keep it to StateVariable class
!e
from ctypes import py_object
class StateVariable:
def __init__(self, category, name, default):
self.__state__ = {
"category": category,
"name": name,
"default": default
}
@lambda cls: setattr(py_object.from_address(id(globals())+tuple.__itemsize__), "value", cls) or cls
class _globals(dict):
__slots__ = ()
def __setitem__(self, name, value):
if isinstance(obj:=self.get(name), StateVariable):
obj.__state__["default"] = value
return
super().__setitem__(name, value)
x = StateVariable("main", "ip adress", "127.0.0.1")
print(x.__state__["default"])
x = "0.0.0.0"
print(x.__state__["default"])
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 127.0.0.1
002 | 0.0.0.0
no way....
(works only for this specific example as you can guess, and you should NEVER use that in real code, but yes, its "possible")
I think I am starting to like this channel lmaooo
dont. its purely for cursed ideas and hacking python. its not practical.
but it's fun (:
sure.
how did u even came up with that?...
uh, i just know a thing or two about some internal stuff i guess. hacking builtins like that is common here
ah that sick... u should contribute to python repo hehe
Speak of fun
#esoteric-python message
The py_object isn't my code btw, someone else helped me
yes
this only works for globals
probably better to set a tracing function, and check for assignments to a variable containing such a thing
can any1 golf this more
while((i:=input)("start? ")=="yes")):
a=i("equation? ").replace("x","*");x=i("number: ");y=i("number: ");print(eval(x+a+y))```
while((i:=input)("start? ")=="yes")):
a=i("equation? ").replace("x","*");x=i("number: ");print(eval(x+a+i("number: ")))
while((i:=input)("start? ")=="yes"):
a=i("equation? ").replace("x","*");x,y=eval("i('number: '),"*2);print(eval(x+a+y))
oh, yours is better
i=input
while"yes"==i("start? "):
a=i("equation? ").replace("x","*");x=i("number: ");print(eval(x+a+i("number: ")))
hmm, maybe a.join?
i=input
while"yes"==i("start? "):
print(eval(i("equation? ").join(eval("i('number: '),"*2))))
clever, but you forgot the .replace
oh right
i=input
while"yes"==i("start? "):
print(eval(i("equation? ").replace(*"x*").join(eval("i('number: '),"*2))))
``` pretty sure thats still shorter
yea
a
why hasn't anyone done this yet ```diff
- while"yes"==i("start? "):
- print(eval(i("equation? ").replace("x").join(eval("i('number: '),"*2))))
- while"yes"==i("start? "):print(eval(i("equation? ").replace("x").join(eval("i('number: '),"*2))))
i=input
while"yes"==i("start? "):print(eval(i("equation? ").replace(*"x*").join(eval("i('number: '),"*2))))
good point
oh, you can actually store nans and infinity in the floats binary, interesting
!e
import struct
nan = float("nan")
inf = float("inf")
neg_inf = float("-inf")
print(nan, inf, neg_inf)
pack_unpack = lambda v: struct.unpack(">f", struct.pack(">f", v))
print(pack_unpack(nan), pack_unpack(inf), pack_unpack(neg_inf))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | nan inf -inf
002 | (nan,) (inf,) (-inf,)
yes
its just ieee754
its just ieee754 if you know what ieee754 is 😄
You can even store many different NaNs, I'm guessing :)
yep
The IEEE Standard for Floating-Point Arithmetic (IEEE 754) is a technical standard for floating-point arithmetic established in 1985 by the Institute of Electrical and Electronics Engineers (IEEE). The standard addressed many problems found in the diverse floating-point implementations that made them difficult to use reliably and portably. Many...
:3
actually idk if you can get a sNAN in python float
because of the way it's implemented
that sounds like a really bold move of them to include nans and infinity to the float number implementation
it's the standard used by basically all modern software and hardware, those values are useful for determining the results of operations, overflow/underflow will result in infinities and nan is for operations that have an undefined result like n/0
Very clever standard
made a brainfuck -> python compiler but it doesn't seem to work
def brainfuck(data, execute=True):
code = ""
i = 0
def add_instruc(code, instruc):
code += "\t" * i
code += instruc
code += "\n"
return code
code += "p=0\ns=[0]*30000\n"
for char in data:
match (char):
case ">":
code = add_instruc(code, "p += 1")
code = add_instruc(code, "if p > 30000:")
i += 1
code = add_instruc(code, "p = 0")
i -= 1
case "<":
code = add_instruc(code, "p -= 1")
code = add_instruc(code, "if p < 0:")
i += 1
code = add_instruc(code, "p = 29999")
i -= 1
case "+":
code = add_instruc(code, "s[p] = (s[p] + 1) & 0xff")
case "-":
code = add_instruc(code, "s[p] = (s[p] - 1) & 0xff")
case ".":
code = add_instruc(code, "print(chr(s[p]), end=\"\")")
case ",":
# fuck inputs
continue
case "[":
code = add_instruc(code, "while s[p] == 0:")
i += 1
case "]":
i -= 1
if execute:
exec(code)
return code
help
!=*
there's a golfed version of this somewhere
or just while s[p]:
other than that it looks fineish, you should probably describe your issue if you expect any real help
esoteric help :>
figure out what's wrong before the helpee says what is
apparently i did
lol
np
thats called transpiler not compiler
transpiler is a type of compiler
!e
import inspect
INDENT = " " * 4
def f() -> type:
name, *attrs = (inspect.stack()[1].code_context or "")[0].partition("#")[2].strip().split()
init_src = f"def __init__(self, {', '.join(attrs)}):{''.join(f'\n{INDENT*2}self.{attr} = {attr}' for attr in attrs)}"
fstring = f"{name}({', '.join(f'{attr}={{self.{attr}}}' for attr in attrs)})"
repr_src= f"def __repr__(self):\n{INDENT*2}return f'{fstring}'"
class_src = f"class {name}:\n{INDENT}{init_src}\n{INDENT}{repr_src}"
exec(class_src)
cls: type = locals()[name]
return cls
Datum = f() # Datum x y z
print(Datum(1, 2, 3))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
Datum(x=1, y=2, z=3)
Where have to define x, y, z tho
in the comment
It read the comment?
yes
inspect.stack()[1].code_context and then get the comment with string operations whatever
Ah
does not work on the REPL in <3.13
!e
import ctypes
import mmap
def is_even(n: int) -> bool:
return (n&1==0)
ftype = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_int)
buf = mmap.mmap(-1, mmap.PAGESIZE, prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC)
fpointer = ctypes.c_void_p.from_buffer(buf)
_ = buf.write(
b'\x8b\xc7' + # mov eax, edi
b'\x83\xe0\x01' + # and eax, 1
b'\x0f\x94\xc0' + # test eax, eax
b'\xc3' # ret
)
asm_is_even = ftype(ctypes.addressof(fpointer))
for n in range(10):
print(f"{n}: {asm_is_even(n) == is_even(n)}")
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | 0: True
002 | 1: True
003 | 2: True
004 | 3: True
005 | 4: True
006 | 5: True
007 | 6: True
008 | 7: True
009 | 8: True
010 | 9: True
whoa that is neat
what happened to W^X ?
💀
will this work on windows? (probably not, if so: is it easy to make it work on windows?)
i tried changing it to fit on windows
but i don't know asm
oh also it didn't work when i did
mmap changes on windows apparently
the asm should work on uh Intel x86_64 or whatever
Played with column-based parallelization yesterday:
with parallel():
print("hello") | sleep(.5)
sleep(1) | print("world")
x = "world" | sleep(.5)
sleep(.5) | print("bye")
print(x) | sleep(1/0)
... | print("kaputt")
It works (although you need a different separator when you need statements on a non-left column as well) ([source])
as well as complex statements such as for loops on the left column
Yep, for anything like that you'll need a seperator starting with # :)
Where is GitHub repo for dont lib

https://github.com/L3viathan/dont
I know I should update the metadata on PyPI
lul
(I've previously built something more useful with this.)
animated donut (thank EvanZhouDev)
https://replit.com/@Taintacles/Donutpy#main.py
Do you really need to copy someone else code to send it here? 💀
Is it the simplest way for __del__ to check if attribute exists in a weird case like this?
class Test:
a: int
def __init__(self, a):
if a < 10:
raise Exception()
self.a = 25
def __getattr__(self, k):
return self.a
def __dir__(self):
return ["a"]
def __dict__(self):
return {}
def __del__(self):
# need to do something with .a value if it's present
# and avoid infinite recursion that would happen if just to
# self.a
try:
v = object.__getattribute__(self, "a")
except AttributeError:
pass
a = Test(9)
Would getattr_static work? https://docs.python.org/3/library/inspect.html#inspect.getattr_static
i feel like if that cacse somehow appears, the client's doing something wrong
you can just do self.a = None in the case its < 10
hasattr?
hasattr will trigger getattr and it will go to infinite loop
hmh
maybe 'a' in dir(self)? or that calls __dir__ (fuck global functions that just call the same dunder istg)
that will call __dir__ 😄
sometimes i hate python
that's nice, didn't knew it existed, it also has an option to provide a default if case attribute is not found
that's also an option, but will need to do self.a = None # type: ignore then
it's not ready for me overriding the dictionary 😄
!e
import inspect
class Test:
a: int
def __init__(self, a):
self.a = 25
print(inspect.getattr_static(self, "a"))
def __dict__(self):
return {}
a = Test(45)
:x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 15, in <module>
003 | a = Test(45)
004 | ^^^^^^^^
005 | File "/home/main.py", line 9, in __init__
006 | print(inspect.getattr_static(self, "a"))
007 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
008 | File "/lang/python/default/lib/python3.12/inspect.py", line 1867, in getattr_static
009 | raise AttributeError(attr)
010 | AttributeError: a
ah I guess that's this note
If the instance
__dict__is shadowed by another member (for example a property) then this function will be unable to find instance members.
I wonder why that's the case
Also why do you have a __dict__ method? Shouldn't it be a dictionary (or just, not be defined)?
I have a case when there is some c-extension class that this class is wrapping.
This is why it overrides __dir__ as it's attributes are dynamic and that way you'll be able to see a list of them. And this is why it overrides __dict__ - so you can get a dictionary of all it's attributes and their values.
Tbh, for me __dir__ is understandable as you do need to get a list of attributes working in interpreter (e.g. when you do entity.<tab> and it prints the list of available attributes) but not sure if it is that useful to override __dict__ instead of just having .todict() method. But that's the way it is rn and I'm not trying to break the existing workflow.
Why not use super().__getattr__
oh, it also works
I guess pyright thrown an error at me I never tried it
I think PyRight is right here, super().__getattr__ doesn't exist as object.__getattr__ doesn't
!e
class Test:
a: int
def __init__(self, a):
if a < 10:
raise Exception()
self.a = 25
def __getattr__(self, k):
return self.a
def __dir__(self):
return ["a"]
def __dict__(self):
return {}
def __del__(self):
print(super().__getattr__("a"))
a = Test(9)
:x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 21, in <module>
003 | a = Test(9)
004 | ^^^^^^^
005 | File "/home/main.py", line 6, in __init__
006 | raise Exception()
007 | Exception
008 | Exception ignored in: <function Test.__del__ at 0x7f8a065ad6c0>
009 | Traceback (most recent call last):
010 | File "/home/main.py", line 19, in __del__
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/LYF4WI73MUV6TOAWZQTGR3YS6Y
super().__getattribute__
!e
@lambda _: _()
class _:
def __format__(_, __):
_.__class__._ = property(lambda _: print(__))
return ""
def __() -> f"{_:Hello, world!}": ...
_._```
:white_check_mark: Your 3.12 eval job has completed with return code 0.
Hello, world!
!e
@lambda _: _()
class :
def format(, ):
.class. = property(lambda _: print())
return ""
def __() -> f"{_:HELLCODE!}": ...
.
:white_check_mark: Your 3.12 eval job has completed with return code 0.
HELLCODE!
can I somehow make this recognize __debugbreak as imported symbol?
I mean the method works, it's just that pylance (and might be other lsps) complains
from debugbreak import __debugbreak as _debugbreak might work
understood
turn off pylance then :3
same error
okay, turned out it is a bug in pyright
Thanks
for a idea
was messing around with some stuff and got this ;-;
!e
import sys
class _:
def format(self, text):
return text
def call(self):
sys.stdout.write(self.format(text="hello"))
_()()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
hello
import sys
class _:
def __format__(self, text):
return text
def __call__(self):
sys.stdout.write(self.__format__(text="hello"))
_()()
!e it's essentially this py import sys class _: def __call__(self): sys.stdout.write("hello") return self _()()()()()()()()()()()()()()()()()()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello
lol
>>> class Foo:
... bar = 3
...
>>> def baz(foo: Foo):
... print(foo.bar)
...
>>> foo = Foo()
>>> Foo.baz = baz
>>> foo.baz()
3``` can anyone explain why this works?
I mean, why not?
any method in the class, when loaded as an attribute from the instance, would be wrapped with something ||(that i don't know the name of :p )|| that automatically gives the first argument of the function as the instance it is loaded as a method from
in other words, ```py
foo = Foo()
foo.baz == some_wrapper(Foo.baz, foo)
im more asking about why when the functcion is added to the class it works with the instance altho the instance was made before the function was aded
because the attribute loading is dynamic..?
huh
it's not a "good luck, you're on your own" thing when an instance is created you know -へ-
that'd be extremely memory inefficient
soo instead of dumping all the information on the instance, a reference to the type of the instance is kept in the instance so stuff from the class ||(that isn't mentioned in __slots__)|| will be available even when not stored on the instance
yup!! :3
that's the 2nd field in the object structure
it's the reason why py_object.from_address(id(x) + 8) works
id(x) returns the base of the object structure of x, 8 is the size ||(in bytes)|| of a Py_ssize_t in 64-bit, and doing id(x) + 8 would be skipping over the first field ||(reference count of x, as a Py_ssize_t)|| and getting the address of the second field ||(the type of x)||
py_object.from_address() basically loads an object pointer from the address given
:D
something like
class method:
def __init__(self, f):
self.f = f
def __get__(self, instance, owner):
return lambda *args, **kwargs: self.f(instance, *args, **kwargs)
wow i could abuse this so hard /hj
why cant it just foo.baz = lambda: Foo.baz(foo)
or smth to that effect
i mean.. it sort of does that?
wrapping a function over a function is simply not efficient :p
:P
it seems like the public name of it is actually just method
In [1]: class test:
...: def f(self):
...: ...
...:
In [2]: type(test().f)
Out[2]: method
mhm
xd
wait a minute.
that's EXACTLY how it works..
yes
!e ```py
from types import MethodType as some_wrapper
class Foo:
bar = 3
def baz(foo):
print(foo.bar)
foo = Foo()
Foo.baz = baz
print(foo.baz)
print(some_wrapper(Foo.baz, foo))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | <bound method baz of <__main__.Foo object at 0x7f15552d7bf0>>
002 | <bound method baz of <__main__.Foo object at 0x7f15552d7bf0>>
!e
class BoundMethod:
def __init__(self, function, instance):
self.function = function
self.instance = instance
def __call__(self, /, *args, **kwargs):
print("Calling bound method")
return self.function(self.instance, *args, **kwargs)
class MethodDescriptor:
def __init__(self, function):
self.function = function
def __get__(self, instance, owner):
print("Getting a bound method")
return BoundMethod(self.function, instance)
class Test:
attr = 42
def method(self):
print(self.attr)
Test.method = MethodDescriptor(method)
test = Test()
test.method()
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | Getting a bound method
002 | Calling bound method
003 | 42
no it's more like this :p ```py
class BoundMethod:
def init(self, function, instance):
self.func = function
self.self = instance
def call(self, /, *args, **kwargs):
print("Calling bound method")
return self.func(self.self, *args, **kwargs)
>>> foo.baz.__self__
<__main__.Foo object at 0x000001E58F459730>
>>> foo.baz.__func__
<function baz at 0x000001E58F232DE0>
hmm.
i thought names would be mangled but it turns out dunders aren't mangled -.(-w-).-
method_wrapper right?
or something like that
ugh i feel like i should know the name of this lmao
this class is confusing because it uses different names in repr depending on its state
or maybe it is not this class...
types.MethodType as well
(they're the same)
Lib/types.py lines 40 to 42
class _C:
def _m(self): pass
MethodType = type(_C()._m)```
ik, I've read it, just that in your code you're gonna use types.MethodType not type(SomeRandomClass().some_random_method)
types does that for all weird types, like FunctionType, LambdaType,CodeType, CoroutineType, etc
that's different
in fact i have no idea where method wrapper gets produced :p
its just called method apparently
where does method-wrapper get produced o.o
its for builtin functions i think
ok no thats wrapper_descriptor
are they the same thing?
wait where'd you get that from-
o
i found it
type(object.__ne__)
>>> [].__add__
<method-wrapper '__add__' of list object at 0x000002785E895DC0>
ok i was right just a bit confused
its wrapper_descriptor but for instances
method but it wraps builtin functions
method_wrapper
built-in types
|_ magic methods
| |_ class -> wrapper_descriptor
| |_ instance -> method-wrapper
|_ normal (instance) methods
| |_ class -> method_descriptor
| |_ instance -> builtin_function_or_method
|_ class methods -> builtin_function_or_method
|_ static methods -> builtin_function_or_method
|_ properties
| |_ class -> member_descriptor
|_ slots
| |_ class -> member_descriptor
|_ __dict__/__weakref__
|_ getset_descriptor
python-defined types
|_ magic methods
| |_ class -> (any callable)
| |_ instance -> method
|_ normal (instance) methods
| |_ class -> (any callable)
| |_ instance -> method
|_ class methods -> classmethod .-> method
|_ static methods -> staticmethod .-> (any callable)
|_ properties
| |_ class -> property
|_ slots
| |_ class -> member_descriptor
ooh you have a table
>>> class X: ...
...
>>> X.__dict__['__dict__']
<slot X.__dict__>
>>> type(X.__dict__['__dict__'])
getset_descriptor
ah =ᵥ='
whoa theres more
python-defined types
|_ class methods -> method
``` im not sure about this one
what do you mean by class method? usually we use `@classmethod` for that
classmethods in builtin classes are `builtin_function_or_method`, that is correct: ```py
>>> type(object.mro)
builtin_function_or_method
>>> type(int.from_bytes)
builtin_function_or_method
yes, they're methods
can you give an example?
>>> class A:
... @classmethod
... def g(t): pass
...
>>> A.g
<bound method A.g of <class '__main__.A'>>
>>> type(A.g)
<class 'method'>
i see
they do appear as classmethod/staticmethod from .__dict__
so i'm probably gonna change the list up a bit
some "magic" methods (dunders) are not wrapper_descriptor but rather method_descriptor
>>> int.__sizeof__?
Help on method_descriptor:
__sizeof__(self, /)
Returns size in memory, in bytes.
i think you should separate magic methods and normal (instance) methods differently: methods that appear in type slots and methods that do not
|_ normal (instance) methods
| |_ class -> (any callable)
| |_ instance -> method
also, if in class it is any callable then on instance you can get any callable as well
you will get method only if method as descriptor returned method, which usually happens when method is function
i hereby decide to not follow this matter any further @~@
!e ```py
import random
random.seed(0.6768157836072148)
x = ''.join(chr(random.randint(97,122)) for _ in range(5))
random.seed(0.26008589044428687)
y = ''.join(chr(random.randint(97,122)) for _ in range(5))
print(x + y)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
helloworld
lol
how did you find the seed?
By a brute force? 😄
Python's random is fully reversible
I assume he picked the first 5 outputs to be 'hello', and then the other 619 required to be random
yup :3
wait 619..?
i'm not sure myself
mersenne twister state can be recovered from 624 consecutive getrandbits outputs
two things here though:
- i don't know if it's possible to recover the seed from state
- it's unpredictable how many times
randintwill callgetrandbits
Is it possible to check if module is partially initialized?
e.g.
a.py:
print(__file__, dir(b))
b.py:
_test = 25
executing a will have output
a.py ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
a.py ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_test', 'a']
so the first time a is fully executed is when it's imported from b module and it's partially initialized
just curious, no use for this
I found 3 seed with 7 match but they ain't consecutive
But in reference, I use range 100-119 while you using a slightly larger one
Got 8 seed now
Also 42 5 consecutive match but 0 6 consecutive match currently
Ok, now 7 6 consecutive match
are you bruteforcing them
and like keeping in a dict or something
matches: dict[int, list[float]] = {}
Yes I am bruteforcing them
No, I put them in stdout and file append output incase anything happened
And using regex in text editor to filter the result
lmao
rip disk
I mean, only result with >= 5 match are stored
Not going to spam my disk with result
>>> 2**64 # number of floats (not really, but i dont care)
18_446_744_073_709_551_616
>>> 26**10 # number of different 10-letter combinations
141_167_095_653_376
>>> 2**64 / 26**10
130673.11464000074
I mean, I use 20 instead of 26
which slightly cheating but I also don't care
(100-119)
>>> 26**10 / 20**10
13.7858491849
``` that is actually pretty good
<3
forgot to showcase
!e
import random
random.seed(463318123)
print(''.join(chr(random.randint(100,119)) for _ in range(10)))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
hsllosorld
just 2
oh yeah, I also didn't use float cuz I'm lazy
!e 20**10/605576493
!e print(20**10/605576493)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
16909.50708682809
hmm, still almost impossible
already ran for 2:40 cpu time (hh:mm)
I mean, if you want to do with 1-7 with translation table, it would be easier
!e print(7**10/605576493)
:white_check_mark: Your 3.12 eval job has completed with return code 0.
0.4664567602362333
ye, that would be done by now if I do that
what does this number mean?
does it show how many seeds you need to check?
It's theoretically how many more times the time I need to take to crack the seed
^ heres the result as I terminated the script
0-6 (7 number) gone wat easier
Already got 9 match
already found
!e
import random
random.seed(51224795)
t = {0: 100, 1: 101, 2: 104, 3: 108, 4: 111, 5: 114, 6: 119}
print(''.join(chr(t[random.randint(0, 6)]) for _ in range(10)))
@fleet bridge @karmic pumice
:white_check_mark: Your 3.12 eval job has completed with return code 0.
helloworld
nice
nice
just need a translation table, which is slightly annoying but I am not making my laptop bruteforce for like 48k hours
compare to ~20mins
here is the result^
!e ```py
import random
random.seed(330108416299333774872520385784)
print(''.join(chr(random.randint(97, 110)) for _ in range(7)))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
denball
Lmao, why is it so absurdly long
havent found any pretty short one
shortest 4047178 (exclude negative)
lol
how did you come up with that number tho
reverse random?
seed(randbelow(10**30))
bruh
you could have just use incrementing number
and you take a call to generate a random number as seed
100 101 110 98 97 108 108
97 110 6
404072 6 100 101 110 98 109 108 108
1404552 6 100 101 110 98 97 108 105
1828376 6 100 101 98 98 97 108 108
1848980 6 101 101 110 98 97 108 108
4047178 7 100 101 110 98 97 108 108
4877249 6 100 101 110 98 109 108 108
4999187 6 100 101 110 98 97 108 106
5237142 6 100 101 110 98 110 108 108
8075296 6 100 101 100 98 97 108 108
also
that was too boring and predictable
but you will know that is the smallest
Who can make infinity loof without using for and while loop please
!e list(iter(int,1))
:warning: Your 3.12 eval job timed out or ran out of memory.
[No output]
@fleet bridge write pure
pure
@fleet bridge I mean write pure code!
!e ```py
:warning: Your 3.12 eval job has completed with return code 0.
[No output]
def rec():
rec()
rec()
how tf did you get this to work without an importError?
why does this work now all of a sudden?
wasnt there some CircularImportError thing over somewhere?
there is no problem, this code shoul work
that is expected
