#esoteric-python
1 messages Β· Page 150 of 1
what's tp_dir
that doesn't exist
it's a dunder method that doesn't correspond to a type slot π€
!e @rapid sparrow ```py
del (object.dict | type('',(),{'ror':lambda _,x:x})())['dir']
class A: ....init #?
print(dir(A()))
@quartz wave :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 4, in <module>
003 | TypeError: object does not provide __dir__
whattt
does not compute
tp_dir is a thing right?
!e
(lambda a: (lambda _,__,___,____,_____: getattr(globals()[(lambda _____: (lambda ____: _.__class__().join((____,____,bin.__module__,____,____)))((lambda ___: (lambda __: chr(_____-((__<<(__<<___))|__)))(((___<<___)-___)>>___))(ord(__)-_____)))(ord(_))], (_.__class__().join([_,__,___,____,_____]))))(*a(map(chr,(lambda _,__: ((lambda: (_<<((_<<(_|__))-_))-(_<<(_<<__)))(),(lambda: (_<<((_<<(_|__))-_))-((__<<__)|(__<<_)|__))(),(lambda: (lambda ___: ___-((_<<(__<<_))+(__<<__)-_)+___)((_<<((__<<_)|__))))(),(lambda: (__<<(_|__|(_<<__)))-((__<<((_<<__)|__))+(((__<<__)|_)<<_)))(),(lambda: (lambda ___: ((__<<__)<<___)+(((__<<___)-___)<<__))(__|_))()))(*(lambda _:(_,(_<<_)))((lambda _:_).__code__.co_nlocals))))))(True.__class__.mro().__class__)((lambda module_str: (lambda e, m_str2: [(lambda list_thingy, m_str3: (lambda inside_code, args=(): eval(f"lambda {','.join(map(str, args)) if len(args) > 0 else ''}: __import__('types').FunctionType(compile(inside_code, 'irrelevant.py', 'exec'), dict(globals(), **locals()))()", dict(globals(), **{"inside_code": inside_code}), locals(),))(f"list_thingy.append(__import__({module_str}))", (list_thingy, m_str3))(list_thingy, m_str3))(e, m_str2), e[0],][-1])((type("list_thingy", (list,), {"__str__": lambda self: "list_thingy"}))(), module_str))("math").sqrt(36))
oh ..
@sick hound :white_check_mark: Your eval job has completed with return code 0.
6.0
Oh it resends a message instead of editing it
the creating a function in a format string part was my fav π₯³
we should index the esoteric snippets in this channel somehow
there's so many good ones she discord search is just.. discord
this may be the full list of type slots:
allocfunc tp_alloc;
PyAsyncMethods* tp_as_async;
PyTypeObject* tp_base;
struct _typeobject* tp_base;
PyObject* tp_bases;
PyObject* tp_cache;
inquiry tp_clear;
destructor tp_dealloc;
destructor tp_del;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
PyObject* tp_dict;
Py_ssize_t tp_dictoffset;
destructor tp_finalize;
freefunc tp_free;
getattrfunc tp_getattr;
PyGetSetDef* tp_getset;
struct PyGetSetDef* tp_getset;
initproc tp_init;
inquiry tp_is_gc;
Py_ssize_t tp_basicsize;
Py_ssize_t tp_itemsize;
getiterfunc tp_iter;
iternextfunc tp_iternext;
PyMemberDef* tp_members;
struct PyMemberDef* tp_members;
PyMethodDef* tp_methods;
struct PyMethodDef* tp_methods;
PyObject* tp_mro;
const char* tp_name;
newfunc tp_new;
richcmpfunc tp_richcompare;
setattrfunc tp_setattr;
PyObject* tp_subclasses;
traverseproc tp_traverse;
vectorcallfunc tp_vectorcall;
Py_ssize_t tp_vectorcall_offset;
unsigned int tp_version_tag;
PyObject* tp_weaklist;
Py_ssize_t tp_weaklistoffset;```
and yes tp_dir is not one
but tp_bases, tp_subclasses etc are
Ah whoops could have sworn tp_dir existed
pass π€’
0 ππ
pass? where?
it said pass earlier when i looked at it
idk i don't see it
it was in class A
!e
del (object.__dict__ | type('',(),{'__ror__':lambda _,x:x})())['__dir__']
class A: ....__init__ #?
print(dir(A()))β
@rapid sparrow :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 4, in <module>
003 | TypeError: object does not provide __dir__
damn it works , im really genuinely impressed π΅ π΅
!e
class T:
pass
del T```
@rapid sparrow :warning: Your eval job has completed with return code 0.
[No output]
is this a sneaky way of altering object's actual dict? and how ..
object.__dict__ | type('',(),{'__ror__':lambda _,x:x})())```
!e print(object.dict | type('',(),{'ror':lambda _,x:x})())
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
{'__new__': <built-in method __new__ of type object at 0x7f60cf7cad00>, '__repr__': <slot wrapper '__repr__' of 'object' objects>, '__hash__': <slot wrapper '__hash__' of 'object' objects>, '__str__': <slot wrapper '__str__' of 'object' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'object' objects>, '__setattr__': <slot wrapper '__setattr__' of 'object' objects>, '__delattr__': <slot wrapper '__delattr__' of 'object' objects>, '__lt__': <slot wrapper '__lt__' of 'object' objects>, '__le__': <slot wrapper '__le__' of 'object' objects>, '__eq__': <slot wrapper '__eq__' of 'object' objects>, '__ne__': <slot wrapper '__ne__' of 'object' objects>, '__gt__': <slot wrapper '__gt__' of 'object' objects>, '__ge__': <slot wrapper '__ge__' of 'object' objects>, '__init__': <slot wrapper '__init__' of 'object' objects>, '__reduce_ex__': <method '__reduce_ex__' of 'object' objects>, '__reduce__': <method '__reduce__' of 'object' objects>, '__subclasshook__': <method '__subclass
... (truncated - too long)
Full output: https://paste.pythondiscord.com/saxevaluqu.txt?noredirect
!e
del object.__dict__["__dir__"]
@plucky plover :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | TypeError: 'mappingproxy' object does not support item deletion
oh
yeah, I was getting that too
!e
o = object.__dict__ | type("", (), {"__ror__": lambda _, x: x})()
print(type(o))
@plucky plover :white_check_mark: Your eval job has completed with return code 0.
<class 'dict'>
weird. shouldn't that say mappingproxy?
i think the | made a copy
so LHS is now a new dict
why doed it cause the error tho..
@plucky plover :white_check_mark: Your eval job has completed with return code 0.
{'__new__': <built-in method __new__ of type object at 0x7f85755ded00>, '__repr__': <slot wrapper '__repr__' of 'object' objects>, '__hash__': <slot wrapper '__hash__' of 'object' objects>, '__str__': <slot wrapper '__str__' of 'object' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'object' objects>, '__setattr__': <slot wrapper '__setattr__' of 'object' objects>, '__delattr__': <slot wrapper '__delattr__' of 'object' objects>, '__lt__': <slot wrapper '__lt__' of 'object' objects>, '__le__': <slot wrapper '__le__' of 'object' objects>, '__eq__': <slot wrapper '__eq__' of 'object' objects>, '__ne__': <slot wrapper '__ne__' of 'object' objects>, '__gt__': <slot wrapper '__gt__' of 'object' objects>, '__ge__': <slot wrapper '__ge__' of 'object' objects>, '__init__': <slot wrapper '__init__' of 'object' objects>, '__reduce_ex__': <method '__reduce_ex__' of 'object' objects>, '__reduce__': <method '__reduce__' of 'object' objects>, '__subclasshook__': <method '__subclass
... (truncated - too long)
Full output: https://paste.pythondiscord.com/omeyesayip.txt?noredirect
HOowWww
Β―\_(γ)_/Β―
It's a bug. It should give the proxy object, but the reversed dunder methods get the actual underlying dict.
its a legit bug?
is it only with mappingproxy?
A bug, but WONTFIX, apparently https://bugs.python.org/issue43838
Iβm okay with closing as "wonβt fix"
best choice given the alternatives, sounds like
sounds like there's two separate bugs, one with __eq__ and one with __ror__ (union)
or two occurences of one bug π
hello world in the most brain fuck complicated godly math sexy science physics way
I request
?
ctrl + f and search hello world :)
not the right channel for this. Look into #βο½how-to-get-help
He has nft pfp
Christian Mayer has the Python One Liners book, it really helped me
Why doesn't bool(True) call True.__bool__()?
>>> (bool.__dict__|type("",(),{"__ror__":lambda _,x:x})())["__bool__"]=lambda x:not x
>>> True.__bool__()
False
>>> bool(True)
True
(I've used the mappingproxy bug to set bool.__bool__ but I was expecting it to propagate the singletons). How can I achieve this?
bool(obj) calls obj->ob_base->tp_as_number->nb_bool(obj) but if you pass it a bool i'm pretty sure the return values are hardcoded
you can't just set the items in the dictionary, you need to modify those structures
it isn't just __eq__
it's all comparisons
Objects/descrobject.c lines 1200 to 1204
static PyObject *
mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
{
return PyObject_RichCompare(v->mapping, w, op);
}```
!e ```py
memory = memoryview((v:=memoryview((b:=bytearray(bytearray.basicsize))).cast('n')).setitem(2,w:=type('',(),{'index':lambda self:setattr(self,'m',[v.release(),b.clear()]and bytearray())or(2 ** (tuple.itemsize * 8) - 1) // 2})())or w.m)
memory[id(250) + int.basicsize] = 0
print(250)
full memory r/w without imports or custom code objects, in one line of code
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
0
@quartz wave ^ in case you want to see something neat
uses the UAF that i found in memoryview.__setitem__
*it might work in windows with some tweaking, idk
already works in windows
in my 7+ months of studying the internals i still can't understand memoryview
all it does is expose a buffer in a way that makes it easier to interact with
!e ```py
memory = memoryview((v:=memoryview((b:=bytearray(bytearray.basicsize))).cast('n')).setitem(2,w:=type('',(),{'index':lambda self:setattr(self,'m',[v.release(),b.clear()]and bytearray())or(2 ** (tuple.itemsize * 8) - 1) // 2})())or w.m)
a = 2**30
memory[id(a) + int.basicsize:id(a) + int.basicsize + 68] = b'\0'*68
memory[id(a) + int.basicsize + 64] = 1
memory[id(a) + object.basicsize] = 17
from math import log2
print(a, log2(a))
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
3121748550315992231381597229793166305748598142664971150859156962533945570856732383447301264550392872193933748069278337112102221659149088111722496 480.0
the memory of a is not used by anything else i guess?
ok
!e ```py
from ctypes import pythonapi, c_uint, c_ssize_t, c_void_p, c_size_t, py_object
from _ctypes import PyObj_FromPtr
n = 100000000
idx = n//30
size = idx + 1
pythonapi.PyObject_Calloc.argtypes = [c_size_t, c_size_t]
pythonapi.PyObject_Calloc.restype = c_void_p
pythonapi._Py_NewReference.argtypes = [c_void_p]
rem = n % 30
mem = pythonapi.PyObject_Calloc(int.basicsize + 4size, 1)
c_ssize_t.from_address(mem + object.basicsize).value = size
py_object.from_address(mem + tuple.itemsize).value = int
pythonapi._Py_NewReference(mem)
c_uint.from_address(mem + int.basicsize + 4idx).value = 1 << rem
a = PyObj_FromPtr(mem)
@quartz wave :warning: Your eval job has completed with return code 0.
[No output]
!e ```py
a = 2**100000000
@quartz wave :warning: Your eval job has completed with return code 0.
[No output]
π€
!timeit py from ctypes import pythonapi, c_uint, c_ssize_t, c_void_p, c_size_t, py_object from _ctypes import PyObj_FromPtr n = 100000 idx = n//30 size = idx + 1 pythonapi.PyObject_Calloc.argtypes = [c_size_t, c_size_t] pythonapi.PyObject_Calloc.restype = c_void_p pythonapi._Py_NewReference.argtypes = [c_void_p] rem = n % 30 ```py
mem = pythonapi.PyObject_Calloc(int.basicsize + 4size, 1)
c_ssize_t.from_address(mem + object.basicsize).value = size
py_object.from_address(mem + tuple.itemsize).value = int
pythonapi._Py_NewReference(mem)
c_uint.from_address(mem + int.basicsize + 4idx).value = 1 << rem
a = PyObj_FromPtr(mem)
del a
@quartz wave :warning: Your timeit job timed out or ran out of memory.
[No output]
maybe you should clear caches
sys._clear_type_cache()
What's the fastest way to square a number?
is a**2 the best, or is there a better?
so filled in circle formula would look something like if a*a + b*b <= c*c:
what if i made a function that took a tuple, and if the tuple exists in a dict, return the value, else calculate the value, write to the dict and return the value would the be the efficientest if I was using this formula a lot?
idc if efficientest isn't a word
but i'm finding a**2 + b**2 <= c**2 to be efficientn't
import functools
@functools.lru_cache
def sum_of_squares(a: float, b: float) -> float:
return a**2 + b**2
import functools
@functools.lru_cache
def is_inside_circle(a: float, b: float, c: float) -> bool:
return a**2 + b**2 <= c**2
!d functools.lru_cache
@functools.lru_cache(user_function)``````py
@functools.lru_cache(maxsize=128, typed=False)```
Decorator to wrap a function with a memoizing callable that saves up to the *maxsize* most recent calls. It can save time when an expensive or I/O bound function is periodically called with the same arguments.
Since a dictionary is used to cache results, the positional and keyword arguments to the function must be hashable.
Distinct argument patterns may be considered to be distinct calls with separate cache entries. For example, f(a=1, b=2) and f(b=2, a=1) differ in their keyword argument order and may have two separate cache entries.
If *user\_function* is specified, it must be a callable. This allows the *lru\_cache* decorator to be applied directly to a user function, leaving the *maxsize* at its default value of 128:
!timeit ```py
a = 3833
b = 21
```py
a**2 + b**2
@quartz wave :white_check_mark: Your timeit job has completed with return code 0.
500000 loops, best of 5: 716 nsec per loop
!timeit ```py
a = 3833
b = 21
```py
a*a + b*b
@quartz wave :white_check_mark: Your timeit job has completed with return code 0.
2000000 loops, best of 5: 152 nsec per loop
wow
~7x faster
so combine the concepts, and...
!timeit
import functools
@functools.lru_cache
def is_inside_circle(a: float, b: float, c: float) -> bool:
return a*a + b*b <= c*c
is_inside_circle(0.0, 0.0, 0.0)
@fleet bridge :white_check_mark: Your timeit job has completed with return code 0.
1000000 loops, best of 5: 198 nsec per loop
you can reverse the operands of <= so like c*c > a*a + b*b
in_circ = __import__("functools").lru_cache(lambda a,b,c:a*a+b*b<=c*c)
!timeit
import functools
from random import uniform
@functools.lru_cache
def is_inside_circle(a: float, b: float, c: float) -> bool:
return a*a + b*b <= c*c
is_inside_circle(uniform(0., 1.), uniform(0., 1.), uniform(0., 1.))
@fleet bridge :white_check_mark: Your timeit job has completed with return code 0.
200000 loops, best of 5: 1.34 usec per loop
micro is larger than nano
ik
this is bad example, because this call is cached
!timeit
from random import uniform
uniform(0., 1.), uniform(0., 1.), uniform(0., 1.)
@fleet bridge :white_check_mark: Your timeit job has completed with return code 0.
200000 loops, best of 5: 970 nsec per loop
1340ns - 970ns = 370ns
!timeit
a = 3833
b = 21
c = 10
in_circ = __import__("functools").lru_cache(lambda a,b,c:a*a+b*b<=c*c)
in_circ(a,b,c)
@floral meteor :white_check_mark: Your timeit job has completed with return code 0.
2000000 loops, best of 5: 171 nsec per loop
it doesnt calculate anything in every iteration
it calculates result once, and then return cached result
exactly
in that case I have feeling there's a really obvious way to half something that's more efficient than a*.5 or a/2
like maybe a>>1
even this can save me whole minutes of staring at a loading bar moving slowly across the screen...
yes
a // 2**n == a >> n
a * 2**n == a << n
a % 2**n == a & (2**n - 1)
def rot13(message): return ''.join(a for i,a in zip(map(chr,range(65,91)), [*map(chr,65+13,91), *reversed(chr,65+13)]) if s == i for s in message) ```
tis no work.
rot13=lambda m:"".join(chr((ord(x)-52)%26+65)for x in m)
i think you have to put the for loop before the if statement
what does >> do?
chops off a binary digit in the binary representation of the integer
random fun thing ```py
is_even = lambda a:a>>1<<1==a
!timeit py a = 5 b = 4 ```py
not a&1; not b&1
@quartz wave :white_check_mark: Your timeit job has completed with return code 0.
2000000 loops, best of 5: 134 nsec per loop
!timeit py a = 5 b = 4 ```py
not a%2; not b%2
@quartz wave :white_check_mark: Your timeit job has completed with return code 0.
2000000 loops, best of 5: 96.1 nsec per loop
!timeit py a = 5 b = 4 ```py
a>>1<<1==a; b>>1<<1==b
@quartz wave :white_check_mark: Your timeit job has completed with return code 0.
1000000 loops, best of 5: 225 nsec per loop
So modulus is good
So a-a%2 might be faster than a>>1<<1?
Or is the equals the chunky boii?
!timeit py a = 5 b = 4 lut = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, ...} ```py
a in lut; b in lut
@quartz wave :white_check_mark: Your timeit job has completed with return code 0.
5000000 loops, best of 5: 63.1 nsec per loop
hello pythonesos
oh thats running pretty well
perfecto π
i made an unsafe custom function that does c PyObject *res = __builtin_expect(((PyLongObject *)args[0])->ob_digit[0] & 1, 0) ? Py_False : Py_True; Py_INCREF(res); return res; and it seems to work pretty well against a set ```py
from timeit import main;main(['-s', "from a_c import is_even; a = 5; b = 4", "is_even(a); is_even(b)"]);main(['-s', "from a_c import is_even; a = 5; b = 4; lut = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, ...}", "a in lut; b in lut"])
10000000 loops, best of 5: 35.1 nsec per loop
10000000 loops, best of 5: 36.3 nsec per loop
NONONONOONONONONONONONOONONONONONONONON
NOT SEMICOLONS

!e ```py
x:str = "Hello World!";
print (x);
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
Hello World!
NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
π€―
Do some stuff with annotations to make C-styled annotations ```py
str: foo = "bar";
done that a while ago in this channel
print((lambda _:(lambda __:_(__)*__))(lambda _: _*_)((lambda _:(__:=sum)(_))([()==()]*int(input('> ')))))
``` Check it out
gives you the cube of number you enter
ok but what difference does it have to print(int(input('>'))**3)
ok ima use the simpler one then
!e ```py
from future import annotations
from ctypes import*
flogbals = py_object.from_address(id(globals())+8).value
class annotations(metaclass=lambda*a:type(*a)()):
() = queue = []
() = type_hints = {}
def setitem(self, cls_name, name):
if name in self.type_hints:
()=self.queue[:]=()
raise Exception(f'Variable '{name}' already declared as '{self.type_hints[name]}'.')
if not self.queue:
self.type_hints[name] = globals()[cls_name]
return
cls, value = self.queue.pop(0)
self.type_hints.update({name:cls})
if cls==cls_name:raise NameError(f'Type {cls} not found')
dict.update(globals(),{name:cls(value)})
class globals(dict):
def missing(self, key):
return builtins.dict.get(key,key)
def setitem(self, key, value):
if key in annotations.type_hints:
dict.update(globals(), {key:annotations.type_hintskey})
return
annotations.queue+=[(globals()[key], value)]
py_object.from_address(id(globals())+8).value=globals
str: n;
n = 6;
str: m = 9;
int: result = n + m;
print(result)
woah
@floral meteor :x: Your eval job has completed with return code 139 (SIGSEGV).
69
got it
thats so cool
I printed "6" + "9"
i wonder what makes it segfault
ok so you've heard of code golfing right
yes
if i cleaned up after, then the exit functions would run fine
ok why didn't you do __import('sys').stdin.read or something
!e ```py
from future import annotations
from ctypes import*
G = py_object.from_address(id(globals())+8)
class annotations(metaclass=lambda*a:type(*a)()):
() = queue = []
() = type_hints = {}
def setitem(self, cls_name, name):
if name in self.type_hints:
()=self.queue[:]=()
raise Exception(f'Variable '{name}' already declared as '{self.type_hints[name]}'.')
if not self.queue:
self.type_hints[name] = globals()[cls_name]
return
cls, value = self.queue.pop(0)
self.type_hints.update({name:cls})
if cls==cls_name:raise NameError(f'Type {cls} not found')
dict.update(globals(),{name:cls(value)})
class globals(dict):
def missing(self, key):
return builtins.dict.get(key,key)
def setitem(self, key, value):
if key in annotations.type_hints:
dict.update(globals(), {key:annotations.type_hintskey})
return
annotations.queue+=[(globals()[key], value)]
G.value=globals
str: n;
n = 6;
str: m = 9;
int: result = n + m;
print (result);
G.value=dict
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
69
happy now?
yes
I didn't know it existed 
whatchu doin boyz
__import?
you meant __import__()?
semicolons
what if i told you im on my wrist watch?
u folker
the keyboard is only three times bigger than my finger
the keyboard is only three times smaller than my finger
well, the tip of finger
π³
!e ```py
from sys import getsizeof as g
a = [1, 2, 3]
b = []
[*map(b.append, a)]
print(f"{g(a)=}\n{g(b)=}")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
001 | g(a)=120
002 | g(b)=88
gonna be fixed in the next 3.10 release
PR 31816 got backported to 3.10
that thing somehow fixed its own issue and the above issue
you got what you wanted, yes?
Yes
Now is it possible for it to work with functions as well ?
Instead of -> T
T func(β¦)
whats wrong with them?
SEMICOLONS
thos looks fun ..
what you would prefer, all one expression? π€
yes
well that is understandable but why ?
why not
program could return something
or better
print the display of whatever and return the usable version of it
in shell scripts you would know if your script is at the end of a pipeline or not
to know whether to display anything
powershell does this actually
it passes pipelines of objects and the last thing is displayed (if its not assigned to a variable)
so yea, lambda
how could you do a recursive lambda
i know i have tried before
python3 -q -i <<<'lambda _,t,i: (print(t % i) or i<5 and _(_, t, i+1)) or ""; print(_(_, "hello %d", 0))'
>>> <function <lambda> at 0x5555db9920>
hello 0
hello 1
hello 2
hello 3
hello 4
hello 5
>>>``` @bronze merlin
hopefully this is esoteric enough
It's esoteric, that's what
from __future__ import braces π¦’
cant you like import all of this stuff-
so it looks cleaner
wait
???????????????????????????????????????????????????????????????????????????????????????????????????????????
- Become employed as Python dev to earn money 2. Buy phone with phone number 3. Hire private investigator to follow someone. 4. Give them the phone and tell them to call you when the location changes.
- Become police officer 6. Subpoena phone company to give location
does
() = queue = []
() = type_hints = {}
do anything special?
there to confuse you
You can consider a line starting with ()= to mean assert empty iterable
Something looking like () = a[:] = () is usually equivalent to a.clear()
It just looks cooler
oh ok π
Makes an empty list from a full list
this is crazy .. to bad it's JavaScript and not Python
i think it is a canvas fingerprinting script
i wonder why there are what looks like memory addresses but made into identifiers
anyway is there any way to translate this to py? π
probably lots and lots and lots of getattr
!e
getattr(eval("".join([*map(lambda _: "%c".__mod__(_), (190 >> 1, 380 >> 2, 1680 >> 4, 27904 >> 8, 7340032 >> 16, 476741369856 >> 32, 2102928824402888884224 >> 64, 39472754562828861761751454462085112528896 >> 128, 11000248477545038565239243575825351246060648543235853583748470480751747315793920 >> 256, 1273741753344546724459532374829555382110539752956277370883738337153567582856986962796178058325855825630553026527716174831106618867134924144911196655577989120 >> 512))]))("".join([*map(lambda _: "%c".__mod__(_), [115, ord("y"), 115])])), "".join([chr(c//255) for c in [25755, 30600, 26775, 29580]]))(127)```
@rapid sparrow :warning: Your eval job has completed with return code 127.
[No output]
no_exit.py
i forgor to do something to hide the "y"
is there any other way to make reference from strings besides eval?
Or from anything for that matter
e.g. if I want to get a teference to sys.exit but without a string like "sys.exit" appearing in program
any idea π€
π
btw this is the whole file in case anybody interested
https://paste.pythondiscord.com/runigapuyi
!e py getattr(__import__(''.join(map(chr,[115,121,115]))),''.join(map(chr,[101,120,105,116])))(0xff)
@rugged sparrow :warning: Your eval job has failed.
A fatal NsJail error occurred
did you break NsJail?
ah. drat
@rapid sparrow :warning: Your eval job has failed.
A fatal NsJail error occurred
#define EXIT_YOURE_F_ED 255
255 stops some command line tools if any process exits with that status doesnt it
xargs or find maybe
what is nsjail 
It's what's used for sandboxing the eval command
oh
s=input();e=".?!:()=-"
for z in e:s=s.replace(z," "+z+" ")
map(lambda d:d!="",s.split())
Can I make this shorter? I used some minifiers and they actually made it longer.
What is it supposed to do? Tokenize [space-separated strings] and those individual characters?
(Also, that lambda is always True)
Yes
and why would that lambda be always true?
split() never creates empty strings
It actually generates empty "" which are useless
It does for me
well I last tested with split(" "), that different?
yes
no-argument split splits on any amount of whitespace, not just one
so no, it never generates ""
the lambda is always true
re.sub("([chars])"," \1 ",input()).split()
\\1 tho
that can definitely reduce it
true
i can just remove the whole map operation
map won't run any way
Golfing, though so
And why wouldnβt it run?
Does the python interpreter get rid of it?
the generator which you are also not saving, nor pulling values from.
_=[z for z in"".join([[z,f" {z} "][z in".?!:()=-"]for z in input()]).split()if z]
# or
s=input()
for z in".?!:()=-":s=s.replace(z,f" {z} ")
_=[d for d in s.split()if d]
is f string smaller?
" "+z+" "
--------!
f" {z} "
# or
" %s "%z
``` yeah
interesring, I thiught it aas longer
input().translate({ord(i):f" {i} "for i in ".?!:()=-"})
what about this
>>> input().translate({ord(i):f" {i} " for i in".?!:()=-"})
hello? there!lmaoa()
'hello ? there ! lmaoa ( ) '```
don't fully understand the specs but that seems about right
[*filter(None,input().translate({ord(i):f" {i} "for i in".?!:()=-"}).split())] for completeness
helllo? there thisisa!test
['helllo', '?', 'there', 'thisisa', '!', 'test']```
!e i don't think we need filter() if we're just gonna .split() with no arguments
i don't think there's a possible case that something is empty so ```py
i = "helllo? there thisisa!test"
=i.translate({ord(i):f" {i} "for i in".?!:()=-"}).split()
print()
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
['helllo', '?', 'there', 'thisisa', '!', 'test']
!e ```py
i = "helllo? there thisisa!test "
=i.translate({ord(i):f" {i} "for i in".?!:()=-"}).split()
print()
odd
i could swear i've had issues with that before
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
['helllo', '?', 'there', 'thisisa', '!', 'test']
nice
very genius
!e wait i think you can remove the ord() ```py
i = "helllo? there thisisa!test "
=i.translate({i:f" {i} "for i in".?!:()=-"}).split()
print()
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
['helllo?', 'there', 'thisisa!test']
k maybe not
i want to add new syntax to python
value |> func1(b)|> func2
# should run something like
func2(func1(value, b))
How would I about doing this?
How would I add a new operator to python?
I know about operator overloading-ish things in python, but that won't cut it
i wanted to start with something existing
Adding entirely new syntax to python is generally discouraged. It can lead to a lot of weird errors. But if you're good with C, you might be able to
i just wanted to tinker with stuff
This might be similar to what you ask
can i over ride what exisiting syntax does with functions?
like
value / func1 / func2
# will give
func1(func2(value))
There are ways to do that
just implement truediv for functions
if func1, and func2 are all special classes with a .__div__ method
with fishhook maybe
You can use that to 'stack' arguments
Here's some code from Scapy that's like what you are thinking
packet = IP(dst="10.11.12.13", src="10.11.12.14")/UDP(chksum=0)/DNS()
how do i change the __div__ for functions?
woah yeah that seems nice
You'd need to define a custom class that inherits from functions? I don't know if that is possible
yeah i am doing that i think
!e
class function:
def __init__(self, *args, **kwargs):
pass
def __repr__(self):
return "new_function"
def new_func():
return 1
print(type(new_func))
@vestal vector :white_check_mark: Your eval job has completed with return code 0.
<class 'function'>
!e
class function:
def __init__(self, *args, **kwargs):
pass
def __repr__(self):
return "new_function"
def new_func():
return 1
print(new_func)
@vestal vector :white_check_mark: Your eval job has completed with return code 0.
<function new_func at 0x7f2e6f027d90>
!e
from functools import partial
from fishhook import hook
@hook(function)
def __rtruediv__(self, value):
return self(value)
42 / print
@plucky plover :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 4, in <module>
003 | NameError: name 'function' is not defined
eh
Yeah
!e
from functools import partial
from fishhook import hook
@hook(type(print))
def __rtruediv__(self, value):
return self(value)
42 / print
@plucky plover :white_check_mark: Your eval job has completed with return code 0.
42
typing.FunctionType?
there
well, yeah
!d
typing
New in version 3.5.
Source code: Lib/typing.py...
!e
from functools import partial
from fishhook import hook
from typing import FunctionType
@hook(FunctionType)
def __rtruediv__(self, value):
return self(value)
42 / print```
@royal whale :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 3, in <module>
003 | ImportError: cannot import name 'FunctionType' from 'typing' (/usr/local/lib/python3.10/typing.py)
Ah
!e
from functools import partial
from fishhook import hook
@hook(type(print))
def __ror__(self, value):
return self(value)
42 | print
@plucky plover :white_check_mark: Your eval job has completed with return code 0.
42
this looks nicer
Wait
type(print) is 'builtin_function_or_method'
Not function
Should you use a lambda?
oh. right
!e
from functools import partial
from fishhook import hook
@hook(lambda _: _)
def __ror__(self, value):
return self(value)
42 | print
@plucky plover :x: Your eval job has completed with return code 139 (SIGSEGV).
001 | Traceback (most recent call last):
002 | File "<string>", line 5, in <module>
003 | File "/snekbox/user_base/lib/python3.10/site-packages/fishhook/__init__.py", line 229, in pwrapper
004 | hook_cls_from_cls(cls, type(f'<{itos(id(cls))}>', (P,), body), **kwargs)
005 | File "/snekbox/user_base/lib/python3.10/site-packages/fishhook/__init__.py", line 185, in hook_cls_from_cls
006 | for subcls in type(cls).__subclasses__(cls):
007 | TypeError: function.__subclasses__() takes no arguments (1 given)
uhh
!e
from functools import partial
from fishhook import hook
@hook(type(lambda:...))
def __ror__(self, value):
return self(value)
42 | lambda x:x```
@royal whale :x: Your eval job has completed with return code 1.
001 | File "<string>", line 8
002 | 42 | lambda x:x
003 | ^^^^^^
004 | SyntaxError: invalid syntax
!e
from functools import partial
from fishhook import hook
@hook(type(lambda: ...))
def __ror__(self, value):
return self(value)
42 | print
@plucky plover :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 8, in <module>
003 | TypeError: unsupported operand type(s) for |: 'int' and 'builtin_function_or_method'
!e
from functools import partial
from fishhook import hook
@hook(type(lambda:...))
def __ror__(self, value):
return self(value)
f = lambda x: x + 1
print(42 | f)
@royal whale :warning: Your eval job has completed with return code 0.
[No output]
Hey I think it worked?
guess you need to implement it for both types
builtin functions and normal functions
i will just take it from here
!e
from functools import partial
from fishhook import hook
@hook(type(lambda:...))
def __ror__(self, value):
return self(value)
f = lambda x: x + 1
print(42 | f)```
@royal whale :white_check_mark: Your eval job has completed with return code 0.
43
Yeah
yeah
Cool, I never thought of doing that before
this is an operator in elixir lang
it is much more complex than this but, who needs that, this will do fine
Ah
thank you so much guys, this was awesome
You're welcome! Happy to help
!e
from fishhook import hook
from functools import partial
from types import FunctionType, LambdaType
@hook(FunctionType)
@hook(LambdaType)
def __ror__(self, val):
if isinstance(val, functools.partial) and val.args == self.__code__.co_argcount - 1:
return self(val)
return partial(self, val)
f = lambda x, y: x + y
print(6 | 5 | f)
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
functools.partial(<function <lambda> at 0x7f9d93c9fd90>, 7)
Personally, I think __rrshift__ and __lshift__ look better:
!e
from fishhook import hook
@hook(type(lambda:...))
def __rrshift__(self, value):
return self(value)
@hook(type(lambda:...))
def __lshift__(self, value):
return self(value)
f = lambda x: x + 1
print(42 >> f)
print(f << 42)
!e
from fishhook import hook
from functools import partial
from types import FunctionType
@hook(FunctionType)
def __ror__(self, val):
if isinstance(val, partial) and len(val.args) == self.__code__.co_argcount - 1:
return self(val)
return partial(self, val)
f = lambda x, y: x + y
print(6 | 5 | f)
lambda's type is just function btw, same as a standard function
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
functools.partial(<function <lambda> at 0x7f29c269bd90>, 7)
Yeah
also i think i did this a little while back, lemme pull up my version π
!e
from fishhook import hook
from functools import partial
from types import FunctionType
@hook(FunctionType)
def __ror__(self, val):
if isinstance(val, partial) and len(val.args) == val.func.__code__.co_argcount - 1:
return self(val)
return partial(self, val)
f = lambda x, y: x + y
print(6 | 5 | f)
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
functools.partial(<function <lambda> at 0x7f570e5dbd90>, 7)
!e
from fishhook import hook
@hook(type(lambda:...))
def __rrshift__(self, value):
return self(value)
@hook(type(lambda:...))
def __lshift__(self, value):
return self(value)
f = lambda x: x + 1
print(42 >> f)
print(f << 42)```
@royal whale :white_check_mark: Your eval job has completed with return code 0.
001 | 43
002 | 43
Cool
!e
from fishhook import hook
from functools import partial
from types import FunctionType
@hook(FunctionType)
def __ror__(self, val):
print(self, val)
if isinstance(val, partial) and len(val.args) == val.func.__code__.co_argcount - 1:
return self(val)
return partial(self, val)
f = lambda x, y: x + y
print(6 | 5 | f)
darn
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
functools.partial(<function <lambda> at 0x7f7719be7d90>, 7)
!e
from fishhook import hook
from functools import partial
from types import FunctionType
@hook(FunctionType)
def __ror__(self, val):
print(self, val)
if isinstance(val, partial) and len(val.args) == val.func.__code__.co_argcount - 1:
return self(val)
return partial(self, val)
f = lambda x, y: x + y
print(6 | 5 | f)
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
001 | <function <lambda> at 0x7f2dc804bd90> 7
002 | functools.partial(<function <lambda> at 0x7f2dc804bd90>, 7)
!e
from fishhook import hook
@hook(type(lambda: 0))
def __rrshift__(self, other):
return self(other)
@hook(type(print))
def __rrshift__(self, other):
return self(other)
@hook(type)
def __rrshift__(self, other):
return self(other)
(
123
>> (lambda x: x*2)
>> str
>> (lambda x: x[::-1])
>> print
)
@languid hare :white_check_mark: Your eval job has completed with return code 0.
642
Epic
really EPYC
Now it's possible, I think, to use both the | and > together to make the |> work. That'd be the __ror__ and __lt__ methods.
nah you'd need something between them
Ah
yea
Wasn't sure
|...> maybe
you could do |- or |+?
this is nice too
Yeah
|-/|+ would allow two separate behaviours too
the 6|5 is getting evaluated first
thats why
hella cringe
hook on type and construct a tuple forget about bitwise or
if we use this instead of just the pipe, we can replace the default unary + to give a type that will then have the reverse or and can hold the stack of args
or here, | with the ellipsis to give the same type that holds the args
then the type has a forward or with a function to call it
sounds nice
hm lemme see
hold on just found an issue
>>> help(hook)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.10/_sitebuiltins.py", line 102, in __call__
import pydoc
File "/usr/lib/python3.10/pydoc.py", line 65, in <module>
import pkgutil
File "/usr/lib/python3.10/pkgutil.py", line 137, in <module>
def iter_importer_modules(importer, prefix=''):
File "/usr/lib/python3.10/functools.py", line 812, in singledispatch
import types, weakref
File "/usr/lib/python3.10/weakref.py", line 93, in <module>
class WeakValueDictionary(_collections_abc.MutableMapping):
File "/usr/lib/python3.10/abc.py", line 106, in __new__
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
MemoryError
is the ellipsis a singleton?
it is
the ellipsis itself doesnt need to contain the information though, just whatever's returned by the ellipsis operation
unazed@spectaculum ~ [SIGSEGV]> python
Python 3.10.4 (main, Mar 23 2022, 23:05:40) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> help(hook)
KeyboardInterrupt
>>> from fishhook import hook
>>>
>>>
>>> @hook(...)
... def __ror__(self, val):
... return val
...
fish: Job 1, 'python' terminated by signal SIGSEGV (Address boundary error)
tuf
type(...)
true
...'s type cold just be entirely replaced with a new user class
i was thinking it might be more extensible to allow user-defined behaviour when data passes through the | ... >
but i don't see what the user would want to be able to do
!e ```py
from ctypes import py_object as p
e = p.from_address(id(...)+8)
class E:ror=lambda s,v:v
e.value = E
print( 69|... )
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
69
like wha?
now this is interesting
how do i return the args but not as a tuple
afaik i can't
the unpacking would need to happen at the callable's side ig
yes, but that would be not pragmatic
i don't think there's very well defined semantics for this atm
nothing that i know of
what's the difference 1 | print vs print | 1
if you allow 1 | 2 | print -> print(2, 1) or print(1, 2)
how would you distinguish that?
is the last element always supposed to be callable? and if so how about 1 | 2 | add_together | 1 | print -> print(1, add_together(1, 2))
last element should be a callable that is what my brain tells me
just to be clear, this way fucking out of my depth
it's a good exercise
yeah
this would just be arbitrary, until there is a functionality which depends on the order
now that functionality will dictate the order from that point onwards
id think 1 | 2 | print would be print(2, 1)
i wouldn't think so in implemenation
since 1 | 2 would be evaluated first, where i guess you'd make a tuple (1, 2) and then pass it down to print
but it makes more sense to print(2, 1)
this is the one with the | right?
@hook(type(lambda: ...))
def __ror__(self, value):
return self(value)
probably easy to fix anyways, inserting parameters into the tuple at the beginning opposed to end
yh that's the binary 1 | print <=> print(1)
yeah
ror for reverse or
hmm another problem: python's magic comparisions are actually a hindrance here
right, now i remember, that's why i used >> here
how do i save a discord convo
ss
in this server we have .bm
.bm
uoohh
.bm
i am fucking spamming ithink
oh
this is awesome
this always ends up happening when I'm coding in python
joe, that is just not right
!e ```py
from ctypes import py_object
c = 4
class Int(int):
def str(self):
return'5'if self==4 else super().str()
C = py_object.from_address(id(c)+8)
C.value = Int
print( 2 + 2 )
C.value = int
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
5
I should probably make fishhook error if hook isn't passed in a type
(s:=setattr,ttt:=type('',(),{'row':3,'board':(b:=[[*range(i, i + 3)]for i in range(1, 10, 3)]),'winner':None,'turn':{1:'x',0:'o'},'mapping':{b[i][j]:[i,j]for j in range(3)for i in range(3)},'draw':False,'c': lambda*s:bool(ttt.draw or ttt.winner)})(),s(ttt,'print_board',lambda:[print('|'.join(f"{i:^{ttt.row}}"for i in row),end=f'\n{"+".join(["-"*ttt.row]*ttt.row)}\n'if row!=ttt.board[-1]else '\n')for row in ttt.board]and None),s(ttt,'check_board',lambda:[s(ttt,'winner',[*w][0])for i in range(3)if any(len(w:=set(i))==1for i in [[ttt.board[i][j]for j in range(3)],[ttt.board[j][i]for j in range(3)]])]or(s(ttt,'winner',ttt.turn[not w])if any((w:=i)==1for i in (len({ttt.board[i][i]for i in range(3)}),len({ttt.board[2-i][i]for i in range(3)})))else None)),s(ttt,'value',lambda t:int(input(f"{t}'s turn: "))),s(ttt,'insert',lambda:[t:=ttt.turn[1],exec('try:''b=1;v=ttt.value(t);x,y=ttt.mapping[v];del ttt.mapping[v];ttt.turn[1],ttt.turn[0]=ttt.turn[0],ttt.turn[1];ttt.board[x][y]=t;\nexcept(KeyError,ValueError):b=0;print("invalid");'),s(ttt,'draw',not bool(ttt.mapping)),ttt.check_board()]and None),s(ttt,'start',lambda:([(ttt.print_board(),ttt.insert())for _ in iter(ttt.c,True)],ttt.print_board(),print(ttt.draw and'Draw!'or f'{ttt.winner} won the game!'))),ttt.start())
4 less execs
!e
from itertools import groupby
import json
lists = [['Lantern', 'Detachable', 'Mask', 'Png'],
['Lantern', 'Detachable', 'Specular', 'Jpeg'],
['Lantern', 'Glass', '2dview', 'Png'],
['Lantern', 'Glass', 'Mask', 'Png'],
['Foo', 'Glass', 'Normal', 'Jpeg'],
['Foo', 'Glass', 'Specular', 'Png'],
['Foo', 'Detachable', 'Normal', 'Png'],
['Foo', 'Detachable', 'Specular', 'Jpeg']]
def treeify(l):
return {
key: treeify([sub[1:] for sub in group if sub[1:]])
for key, group in groupby(l, key=lambda x: x[0])
} if len(l) > 1 else l[0][0]
print(json.dumps(treeify(lists), indent=4))
@primal idol :white_check_mark: Your eval job has completed with return code 0.
001 | {
002 | "Lantern": {
003 | "Detachable": {
004 | "Mask": "Png",
005 | "Specular": "Jpeg"
006 | },
007 | "Glass": {
008 | "2dview": "Png",
009 | "Mask": "Png"
010 | }
011 | },
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/orasixogog.txt?noredirect
Can treeify be golfed beyond this?
from itertools import groupby
f=lambda l:{k:f([s[1:]for s in g if s[1:]])for k,g in groupby(l,key=lambda x:x[0])}if len(l)>1else l[0][0]
I working from the assumption that using the import is the shortest but I am not sure
I had a strange idea to do this using recursive defaultdicts
Yeah this was from a help channel and ivo used setdefault, I had no idea about using that but it seemed longer initially
!e
from pprint import pp
lists = [['Lantern', 'Detachable', 'Mask', 'Png'],
['Lantern', 'Detachable', 'Normal', 'Png'],
['Lantern', 'Detachable', 'Specular', 'Png'],
['Lantern', 'Glass', '2dview', 'Png'],
['Lantern', 'Glass', 'Mask', 'Png'],
['Foo', 'Glass', 'Normal', 'Png'],
['Foo', 'Glass', 'Specular', 'Png'],
['Foo', 'Detachable', 'Specular', 'Png'],
['Foo', 'Detachable', 'Specular', 'Foo']]
def treeify(lists):
result = {}
for l in lists:
current = result
for item in l:
current = current.setdefault(item, {})
return result
pp(treeify(lists))
@primal idol :white_check_mark: Your eval job has completed with return code 0.
001 | {'Lantern': {'Detachable': {'Mask': {'Png': {}},
002 | 'Normal': {'Png': {}},
003 | 'Specular': {'Png': {}}},
004 | 'Glass': {'2dview': {'Png': {}}, 'Mask': {'Png': {}}}},
005 | 'Foo': {'Glass': {'Normal': {'Png': {}}, 'Specular': {'Png': {}}},
006 | 'Detachable': {'Specular': {'Png': {}, 'Foo': {}}}}}
pp?
pretty print
lol
best alias in the stdlib :P
technically shorter I guess x)
f=lambda l:{k:f([s[1:]for s in g if s[1:]])for k,g in __import__('itertools').groupby(l,key=lambda x:x[0])}if len(l)>1else l[0][0]
I have a strange idea, let me try something
I found something that is shorter, but it requires all the nested lists to be reversed :p
wait, hmmm
Oh lol I can pass the key as a positional
f=lambda l:{k:f([s[1:]for s in g if s[1:]])for k,g in __import__('itertools').groupby(l,lambda x:x[0])}if len(l)>1else l[0][0]
f=lambda L:(r:=type('',(dict,),{'__missing__':lambda s,k:[s.setdefault(k,x:=type(s)()),x][1]})(),[(c:=r,[(c:=c[x]) for x in l]) for l in L])[0]
no imports
f=lambda L:(r:=(T:=type('',(dict,),{'__missing__':lambda s,k:[s.setdefault(k,x:=T()),x][1]}))(),[(c:=r,[(c:=c[x]) for x in l]) for l in L])[0]
``` smaller
!e
from fishhook import hook
@hook(int)
def __radd__(self, val):
return val + str(self)
print("2" + 1)
@haughty pagoda :white_check_mark: Your eval job has completed with return code 0.
21
ah finally, noob compliant code
finally js in python
There is a lot going on there π
!e ```py
from pprint import pp
lists = [['Lantern', 'Detachable', 'Mask', 'Png'],
['Lantern', 'Detachable', 'Normal', 'Png'],
['Lantern', 'Detachable', 'Specular', 'Png'],
['Lantern', 'Glass', '2dview', 'Png'],
['Lantern', 'Glass', 'Mask', 'Png'],
['Foo', 'Glass', 'Normal', 'Png'],
['Foo', 'Glass', 'Specular', 'Png'],
['Foo', 'Detachable', 'Specular', 'Png'],
['Foo', 'Detachable', 'Specular', 'Foo']]
lists = [l[::-1] for l in lists]
f=lambda l:{k:f([s for s in g if s])for k,g in import('itertools').groupby(l,key=list.pop)}if len(l)!=1else l[0][0]
pp(f(lists))```
@polar plover :white_check_mark: Your eval job has completed with return code 0.
001 | {'Lantern': {'Detachable': {'Mask': 'Png', 'Normal': 'Png', 'Specular': 'Png'},
002 | 'Glass': {'2dview': 'Png', 'Mask': 'Png'}},
003 | 'Foo': {'Glass': {'Normal': 'Png', 'Specular': 'Png'},
004 | 'Detachable': {'Specular': {'Png': {}, 'Foo': {}}}}}
f=lambda L:(r:=type('',(dict,),{'__missing__':lambda s,k:s.setdefault(k,type(s)())})(),[(c:=r,[(c:=c[x])for x in l])for l in L])[0]
``` smaller
Oh right the list is buggy, there really should be two 'specular ...'
!e len("""f=lambda l:{k:f([s for s in g if s])for k,g in __import__('itertools').groupby(l,key=list.pop)}if len(l)!=1else l[0][0]""")
# your
f=lambda l:{k:f([s[1:]for s in g if s[1:]])for k,g in __import__('itertools').groupby(l,lambda x:x[0])}if len(l)>1else l[0][0]
# my
f=lambda L:(r:=type('',(dict,),{'__missing__':lambda s,k:s.setdefault(k,type(s)())})(),[(c:=r,[(c:=c[x])for x in l])for l in L])[0]
the downside of mine is the need to reverse the internal lists first :p
note no imports!
but I thought the concept of key=list.pop was cool
Yours is equivalent to mine without the ifs though
Indeed π
f=lambda l:{k:f([s[1:]for s in g if s[1:]])for k,g in __import__('itertools').groupby(l,lambda x:x[0])}
f=lambda L:(r:=type('',(dict,),{'__missing__':lambda s,k:s.setdefault(k,type(s)())})(),[(c:=r,[(c:=c[x])for x in l])for l in L])[0]
It also doesnt use recursion
so it is probably faster
f=lambda l:{k:f([s[1:]for s in g if s[1:]])for k,g in __import__('itertools').groupby(l,lambda x:x[0])}
f=lambda L:(r:=type('',(dict,),{'__missing__':lambda s,k:s.setdefault(k,type(s)())})(),[(c:=r,[(c:=c[x])for x in l])for l in L])[0]
f=lambda L:(r:=(T:=type('',(dict,),{'__missing__':lambda s,k:s.setdefault(k,T())}))(),[(c:=r,[c:=c[x]for x in l])for l in L])[0]
i used this code as reference implementation
wow
f=lambda L:(r:={},[(c:=r,[c:=c.setdefault(x,{})for x in l])for l in L])[0]
!e
f=lambda L:(r:={},[(c:=r,[c:=c.setdefault(x,{})for x in l])for l in L])[0]
from pprint import pp
lists = [['Lantern', 'Detachable', 'Mask', 'Png'],
['Lantern', 'Detachable', 'Normal', 'Png'],
['Lantern', 'Detachable', 'Specular', 'Png'],
['Lantern', 'Glass', '2dview', 'Png'],
['Lantern', 'Glass', 'Mask', 'Png'],
['Foo', 'Glass', 'Normal', 'Png'],
['Foo', 'Glass', 'Specular', 'Png'],
['Foo', 'Detachable', 'Specular', 'Png'],
['Foo', 'Detachable', 'Specular', 'Foo']]
pp(f(lists))
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | {'Lantern': {'Detachable': {'Mask': {'Png': {}},
002 | 'Normal': {'Png': {}},
003 | 'Specular': {'Png': {}}},
004 | 'Glass': {'2dview': {'Png': {}}, 'Mask': {'Png': {}}}},
005 | 'Foo': {'Glass': {'Normal': {'Png': {}}, 'Specular': {'Png': {}}},
006 | 'Detachable': {'Specular': {'Png': {}, 'Foo': {}}}}}
the smallest
Lmao
modify:
Grammar/Tokens (add the |> token)
Grammar/python.gram (add a grammar rule for the operator)
Parser/Python.asdl (add a node-type for it under operator)
Python/ast_opt.c (not required, only for optimization)
Python/compile.c (convert the node into bytecode)
then regenerate using either PCbuild\build.bat --regen in windows or idk in linux
then build using either PCbuild\build.bat -e in windows or idk in linux
that's how i would do it
there's also a devguide https://devguide.python.org/
and also first answer is outdated and is not specifically for binary operations
what i said in the message above ^^
https://github.com/SebastiaanZ/pypethon could be helpful
ok but either it's py value |> func1(b) |> func2() or it should run something like ```py
func2(func1(b)(value))
i think i implemented it ```py
def a(x, y): print(x * y)
...
5 |> a(4)
20
it's called adding new syntax to python
π
what's the new bytecode called
what new bytecode
does |>not generate a new opcode?
no
i didn't have to add a new instruction for it
you got the patchfile for it? i wanna take a look
idk what a patchfile is
git patch file, or some way to compile ur version
i manually edited it on the github website
odd, getting a compilation error error: βCallPipeβ undeclared (first use in this function), same with Comp
you have to regen first
also fixed the Comp thingy
>>> 1 |> print
fish: Job 1, './python' terminated by signal SIGSEGV (Address boundary error)
damn
is it only valid when you're calling functions? i.e. 1 |> print()
i think the code was fairly similar to mine in python comparing fn.__code__.co_argcount to allow partial applications
What's the code for that?
why is it segfaulting
ima fix that
(s:=setattr,ttt:=type('',(),{'row':3,'board':(b:=[[*range(i,i+3)]for i in range(1,10,3)]),'winner':None,'turn':{1:'x',0:'o'},'mapping':{b[i][j]:[i,j]for j in range(3)for i in range(3)}})(),s(ttt,'print_board',lambda:[print('|'.join(f"{i:^{ttt.row}}"for i in row),end=f'\n{"+".join(["-"*ttt.row]*ttt.row)}\n'if row!=ttt.board[-1]else '\n')for row in ttt.board]and None),s(ttt,'check_board',lambda:[s(ttt,'winner',[*w][0])for i in range(3)if any(len(w:=set(i))==1for i in [[ttt.board[i][j]for j in range(3)],[ttt.board[j][i]for j in range(3)]])]or(s(ttt,'winner',ttt.turn[not w])if any((w:=i)==1for i in (len({ttt.board[i][i]for i in range(3)}),len({ttt.board[2-i][i]for i in range(3)})))else None)),s(ttt,'value',lambda t:int(input(f"{t}'s turn: "))),s(ttt,'i',lambda v,t:(x:=ttt.mapping[v],ttt.mapping.pop(v),c:=ttt.turn[1],ttt.turn.__setitem__(1,ttt.turn[0]),ttt.turn.__setitem__(0,c),ttt.board[x[0]].__setitem__(x[1],t))),s(ttt,'insert',lambda:[t:=ttt.turn[1],(b:=1,ttt.i(v,t))if (v:=ttt.value(t))in range(1,10)and v in ttt.mapping else (print('Invalid!'),b:=0),b and ttt.check_board()]and None),s(ttt,'start',lambda:([(ttt.print_board(),ttt.insert())for _ in iter(lambda*s:bool(not ttt.mapping or ttt.winner),True)],ttt.print_board(),print(ttt.winner and f'{ttt.winner} won the game!'or 'Draw!'))),ttt.start())
finally 0 execs
!e py exec((164341359529058470404239104646974828831685182826281).to_bytes(21,'big'))
@split salmon :white_check_mark: Your eval job has completed with return code 0.
Hello World!
wait what's this for
holy
tic tac toe
nah you capping
xD
(s:=setattr,T:=type('',(),{'R':3,'B':(b:=[[*range(i,i+3)]for i in range(1,10,3)]),'W':None,'Tn':{1:'x',0:'o'},'M':{b[i][j]:[i,j]for j in range(3)for i in range(3)}})(),s(T,'P',lambda:[print('|'.join(f"{i:^{T.R}}"for i in R),end=f'\n{"+".join(["-"*T.R]*T.R)}\n'if R!=T.B[-1]else '\n')for R in T.B]and None),s(T,'C',lambda:[s(T,'W',[*w][0])for i in range(3)if any(len(w:=set(i))==1for i in [[T.B[i][j]for j in range(3)],[T.B[j][i]for j in range(3)]])]or s(T,'W',T.Tn[not w])if any((w:=i)==1for i in (len({T.B[i][i]for i in range(3)}),len({T.B[2-i][i]for i in range(3)})))else None),s(T,'value',lambda t:int(v if(v:=input(f"{t}'s turn: ")).isdigit()else '-1')),s(T,'i',lambda v,t:(x:=T.M[v],T.M.pop(v),c:=T.Tn[1],T.Tn.__setitem__(1,T.Tn[0]),T.Tn.__setitem__(0,c),T.B[x[0]].__setitem__(x[1],t))),s(T,'I',lambda:[t:=T.Tn[1],(b:=1,T.i(v,t))if(v:=T.value(t))in range(1,10)and v in T.M else(print('Invalid!'),b:=0),b and T.C()]and None),s(T,'S',lambda:([(T.P(),T.I())for _ in iter(lambda*s:bool(not T.M or T.W),True)],T.P(),print(T.W and f'{T.W} won the game!'or'Draw!'))),T.S())
shortened the names and stuff
ah shit, it broken now. welp 
(s:=setattr,R:=range,T:=type('',(),{'B':(b:=[[*R(i,i+3)]for i in R(1,10,3)]),'W':None,'Tn':{1:'x',0:'o'},'M':{b[i][j]:[i,j]for j in R(3)for i in R(3)}})(),s(T,'P',lambda:[print('|'.join(f"{i:^3}"for i in r),end=f'\n{"+".join(["-"*3]*3)}\n'if r!=T.B[-1]else '\n')for r in T.B]and None),s(T,'C',lambda:[s(T,'W',[*w][0])for i in R(3)if any(len(w:=set(i))==1for i in [[T.B[i][j]for j in R(3)],[T.B[j][i]for j in R(3)]])]or(s(T,'W',T.Tn[not w])if any((w:=i)==1for i in (len({T.B[i][i]for i in R(3)}),len({T.B[2-i][i]for i in R(3)})))else None)),s(T,'value',lambda t:int(input(f"{t}'s turn: "))),s(T,'i',lambda v,t:(x:=T.M[v],T.M.pop(v),c:=T.Tn[1],T.Tn.__setitem__(1,T.Tn[0]),T.Tn.__setitem__(0,c),T.B[x[0]].__setitem__(x[1],t))),s(T,'I',lambda:[t:=T.Tn[1],(b:=1,T.i(v,t))if(v:=T.value(t))in R(1,10)and v in T.M else (print('Invalid!'),b:=0),b and T.C()]and None),s(T,'S',lambda:([(T.P(),T.I())for _ in iter(lambda*s:bool(not T.M or T.W),True)],T.P(),print(T.W and f'{T.W} won the game!'or 'Draw!'))),T.S())
this should work
Damn π
niiiiiiiiiiiiiiiiiiiiiiiiiiiiiice
(w:=[0],e:=[0],b:=[0],j:=lambda a,b=0:a.__setstate__(b),P:=print,R:=range,c:=lambda:(b:=[f" {_} "for _ in R(1,10)],[b.__setitem__(_,list(map(int,bin(p[0])[2:].zfill(9)))[_]*c or b[_])for p,c in((w," o "),(e," x "))for _ in R(9)],P("\n---+---+---\n".join(["|".join(b[_:_+3])for _ in R(0,9,3)]))),c(),q:=iter([(w," o "),(e," x ")]),[(i:=iter([1]),[(n:=input(f"{d[1]}'s turn: "),(n.isdigit()and(0<(I:=int(n))<10)and(r:=2**(9-I))&b[0]<1 or(P("Invalid!"),c(),j(i))))for _ in i],p.__setitem__(0,g:=p[0]|r),b.__setitem__(0,w[0]|e[0]),c(),p!=e or j(q),any([any(g&(_:=292>>i)==_ for i in R(3)),any(g&(_:=448>>i*3)==_ for i in R(3)),g&273==273 or g&84==84])<1 or(j(q,3),P(f"{d[1]} won the game!")),b!=[511]or(j(q,3),P("Draw!")))for p,d in q])
-268 characters
also added a QoL update which invalidates non-integer inputs
i got thoroughly nerd-sniped on this
damn i just realised i didn't need a whole variable
(w:=[0,0],j:=lambda a,b=0:a.__setstate__(b),P:=print,R:=range,c:=lambda:(b:=[f" {_} "for(_)in R(1,10)],[[b.__setitem__(_,(w[p]&(h:=1<<8-_)==h)*c or b[_])for(p,c)in((0," o "),(1," x "))for(_)in R(9)]],P("\n---+---+---\n".join(["|".join(b[_:_+3])for(_)in R(0,9,3)]))),c(),q:=iter([(0," o "),(1," x ")]),[(i:=iter([1]),[(n:=input(f"{d[1]}'s turn: "),(n.isdigit()and(0<(I:=int(n))<10)and(r:=1<<9-I)&(w[0]|w[1])<1 or(P("Invalid!"),c(),j(i))))for(_)in i],w.insert(p,g:=w.pop(p)|r),c(),p!=1 or j(q),(j(q,3),P(f"{d[1]} won the game!"))if any(g&i==i for(i)in[292,146,73,448,56,7,273,84])else(w[0]|w[1]!=511)or(j(q,3),P("Draw!")))for(p,d)in q])
there, also fixed a bug LMAO
632 chars aye
wtf is this channel lol

470884583684964352
ΠΎΡΠΈΠ½Ρ Ρ ΠΎΡΠΎΡΠΈΠΉ!!
Ρ Π΄ΡΠΌΠ°Ρ Π΅ΡΠΎ ΠΎΡΠΈΠ½Ρ ΡΡΡΠ΄Π½ΠΎ!
ΡΡΡΠ΄Π½ΠΎ ΡΠΈΡΠ°ΡΡ ΡΠΎΠΆΠ΅
ok?
@quartz wave your profile description is very good
Golfing, Python VM languages, obfuscation, code gore and other general Python weirdness
what is code gore? is it obfuscation?
code golf. not gore. damn
wow ungolfed code
what's the largest print statement you can find?
it just needs to print out hello world
Maybe just a Brainfuck interpreter running a simple Hello World program
obfuscation is hiding the purpose of the code.
code gore is traumatising anyone who tries to read the code, or writing the code extremely disgustingly
.bm
Congratulations you successfully coded minified javascript
i need effective string obfucation (dont give me shitty exec functions)
depends on your meaning of "effective"
unable to get source or just hard
you can always get back the string by just running the obfuscated version though

i mean hidden or unreadable
hidden aka mixed with a bunch of bullshit
just encrypt it?
so uh bcrypt?
That's a hash..
You don't "encrypt" code
oh right. mb
but u "encrypt" strings
how to global a function from importation?
like
globals import('random').randint
!e
randint = __import__('random').randint
print(randint(1, 10))
@wheat river :white_check_mark: Your eval job has completed with return code 0.
3
to global scope
it is global....
globals()["randint"]=__import__("random").randint?
globals().__setitem__("randint",__import__('random').randint) works too
globals()._setitem__('randint',__import__('random').randint)```
yoi have the same thought
items xD
except i forgor the parenthisis at glovals lol
items() item and crap my minds blowing up
1 more _
all good π
humiliating question π
(lambda u,n:(lambda k:u(k))({n:__import__(n)}))(globals().update,'randint')
π€
!e or even worse...
import sys
def f(n):
g = sys._getframe(1)
k = g.f_globals.__ior__
k({n:__import__("random").__getattribute__(n)})
f("randint")
print(randint)
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
<bound method Random.randint of <random.Random object at 0x5570f85352d0>>
globals modification yas?
Ok thanks
hi
Is it possible to alter the intermediate bytecode of a module merely by doing an import?
example doing something so that
def func(a, b, c): ... # Curried in an extension
func(1)(2)(3)
Doesnt actually call func three times but instead waits until all param have been given until the call is actually executed
Wait I think I am just asking if it possible to implement my own __future__ kind of flags without recompiling python
i don't think so? you can't get the importing module from a submodule by using inspect.currentframe().f_back because importlib strips any previous frames in the process of importing a module
it would be more pythonic to have something like import my_module; my_module.install_hooks()
then that can use frame introspection to find all function objects, and change their __code__, or better yet use decorators
Humm that wouldnt really work, I am mainly asking about this for performance, otherwise I know this can be done via decorators but the problem is that partials of a function could be passed around many other objects
Because doing func(1) would give me a new partial function which waits to be called again 2 more times, what would be idea is that calling a curried function would not actually call the function but rather store the argument in a buffer until the buffer reached size of 3
And if the object went out of scope and was garbage collected the buffer would be too
ah i see
!e (t:=lambda x:(__import__('sys').setrecursionlimit(pow(2,31)-1),x(x)))(t)
lol
!e (t:=lambda x:(__import__('sys').setrecursionlimit(pow(2,31)-1),x(x),print("Lambda recursion")))(t)
lol
!e __import__('time').sleep(0.5); print("Hi!")
!e __import__('time').sleep(3.5); print("Hi!")
!e __import__('time').sleep(5); print("Hi!")
lol
def func(a):
def func2(b):
def func3(c):
return a * b * c # Replace with your code
return func3
return func2```
One-liner: ```py
lambda a:lambda b:lambda c:a*b*c```
Yes I am aware, but that function is going to be significantly slower then func(a, b, c)
taking a look at a way rn
yes, many look-ups
gtg sleep
bye
i couldn't implement any more efficient way than doing that above ^ with nested functions
having issues with holding a non-persistent buffer between curried calls
it might need to be more of a lower level implementation, but i don't see any way to do it better in python
Oh yeah this has to be at least a change in the bytecode
How tho?
I am pretty sure, I think the ast can be the same, that is why I was wandering if it is possible to say pip install currying-package and then on a module do something like import currying and then change how the module is impolemented
No clue, I never really messed with pythons bytecode but I see people doing that here π
Fuk sleeping
I'll try later
I've read bytecode, but never wrote any
And, you can't do that AFAIK in bytecode @primal idol
Doing this at all or you mean doing this and also having that being done by an import "flag" vs using a new python interpreter?
What
Like, my question was if this was doable by doing an import, I assume this could "definitely"(ignoring possible side effects which could make this harder to use other then a toy) be done if one were to change pythons ast and bytecode, compile it and use a new interpreter
But that wouldnt be as easy for an user as just an import like future imports
!e
def wait_args(func):
num_args = func.__code__.co_argcount
a = []
def wrapper(*args):
if args:
a.append(args[0])
if len(a) == num_args:
return func(*a)
return wrapper
return wrapper
@wait_args
def func(a, b, c):
return a + b + c
print(func(1)(2)(3))
@wheat river :white_check_mark: Your eval job has completed with return code 0.
6
!e
def wait_args(func):
num_args = func.__code__.co_argcount
a = []
k = {}
def wrapper(*args, **kwargs):
a.extend(args)
k.update(kwargs)
if len(a) + len(k) == num_args:
return func(*a, **k)
return wrapper
return wrapper
@wait_args
def func(a, b, c):
return a + b + c
print(func(1, c=10)(2))
@wheat river :white_check_mark: Your eval job has completed with return code 0.
13
Humm, that is a neat use of co_argcount x)
but just returning the lambda is faster then that I think
ok what if it has varpargs and varkwargs
also positional-only arguments and keyword-only arguments
sp = lambda a, b, c: a + b + c
er = lambda a:lambda b:lambda c:a+b+c
def wait_args(func):
num_args = func.__code__.co_argcount
a = []
k = {}
def wrapper(*args, **kwargs):
a.extend(args)
k.update(kwargs)
if len(a) + len(k) == num_args:
return func(*a, **k)
return wrapper
return wrapper
@wait_args
def func(a, b, c):
return a + b + c
>>> %timeit sp(1, 3, 6)
150 ns Β± 31.8 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
>>> %timeit er(1)(3)(6)
525 ns Β± 109 ns per loop (mean Β± std. dev. of 7 runs, 1000000 loops each)
>>> %timeit func(1)(3)(6)
867 ns Β± 144 ns per loop (mean Β± std. dev. of 7 runs, 1000000 loops each)
obv doing it manually would be faster...
Yes but I mean, the manual one is already suboptimal, I read a bit on future flags and I think one could not make their one plugin future flag it seems
what do you think should be done for ```py
def func(foo, *other, bar, **kwother):
...
inspect.getfullargspec??
i meant how should wrapper return
if foo and bar is filled (minimum)
I would expect that as soon as you are only left with * and ** it should return
ya
i'm thinking like if there are *stuff and **otherstuff then an empty call would return the actual function call
like func(1)(bar=2) should be like the minimum return call, but then idk how we can get what they go for after like func(1)(bar=2)(12)(b=10)
ya i guess thats reasonable, the last () marks the end of it
is it well defined in other languages to curry functions with keyword arguments?
idk if haskell has kwargs
Nope, it doesnt have kwargs
in any case i think lazy evaluation is better, try evaluate the value when it's used in something that needs it
otherwise something like f(1)(bar=2)(12)(b=10) can sit in memory as a lazily evaluated object
that'd require changing the semantics for it though
this blog does it like that https://codeburst.io/perpetual-currying-in-javascript-5ae1c749adc5
It is what the returns library does too
I think
!e
from functools import partial as _partial
from functools import wraps
from inspect import BoundArguments, Signature
from typing import Any, Callable, Tuple, TypeVar, Union
_ReturnType = TypeVar('_ReturnType')
def partial(
func: Callable[..., _ReturnType], *args: Any, **kwargs: Any,
) -> Callable[..., _ReturnType]:
return _partial(func, *args, **kwargs)
def curry(function: Callable[..., _ReturnType]) -> Callable[..., _ReturnType]:
argspec = Signature.from_callable(function).bind_partial()
def decorator(*args, **kwargs):
return _eager_curry(function, argspec, args, kwargs)
return wraps(function)(decorator)
def _eager_curry(
function: Callable[..., _ReturnType],
argspec,
args: tuple,
kwargs: dict,
) -> Union[_ReturnType, Callable[..., _ReturnType]]:
intermediate, full_args = _intermediate_argspec(argspec, args, kwargs)
if full_args is not None:
return function(*full_args[0], **full_args[1])
def decorator(*inner_args, **inner_kwargs):
return _eager_curry(function, intermediate, inner_args, inner_kwargs)
return wraps(function)(decorator)
_ArgSpec = Union[Tuple[None, Tuple[tuple, dict]],Tuple[BoundArguments, None],]
def _intermediate_argspec(
argspec: BoundArguments,
args: tuple,
kwargs: dict,
) -> _ArgSpec:
full_args = argspec.args + args
full_kwargs = {**argspec.kwargs, **kwargs}
try:
argspec.signature.bind(*full_args, **full_kwargs)
except TypeError:
return argspec.signature.bind_partial(*full_args, **full_kwargs), None
return None, (full_args, full_kwargs)
#############################
@curry
def func(foo, *other, bar, **kwother):
print(foo)
print(other)
print(bar)
print(kwother)
func(3)()()(baz=8)()()()(bar=3)
@primal idol :white_check_mark: Your eval job has completed with return code 0.
001 | 3
002 | ()
003 | 3
004 | {'baz': 8}
that's a damn lot of annotations
Yeah a lot of his work went into making everything in the library as compatible with mypy as possible using mypy plugins
i thought mypy and pyright both had partial support
holy shit
This synthesizes all the overloads the function can have though
!e ```py
from sys import _getframe
from dis import opmap
from ctypes import c_char
thanks chilaxan :)
def builtinexc(exc, depth=1):
frame = _getframe(1 + depth)
addr = id(co := frame.f_code.co_code) + bytes.basicsize - 1
mem = (c_char * len(co)).from_address(addr)
mem[frame.f_lasti + 2:frame.f_lasti + 4] = bytes([opmap['RAISE_VARARGS'], 1])
return exc
def wait_args(func):
num_pargs = (code := func.code).co_posonlyargcount
num_nonkwargs = code.co_argcount
num_nargs = num_nonkwargs - num_pargs
num_kwargs = code.co_kwonlyargcount
num_required_args = num_nonkwargs - (len(func.defaults) if func.defaults else 0)
start_kwargs = num_nargs + (not not code.co_flags & 4) + 1
required_kwargs = {x for x in code.co_varnames[start_kwargs:start_kwargs + num_kwargs]
if x not in func.kwdefaults} if func.kwdefaults else {*()}
has_arbitrary = code.co_flags & 12
a = []
k = {}
k_keys = k.keys()
def wrapper(*args, **kwargs):
a.extend(args)
for key in kwargs:
if key in k:
return builtinexc(SyntaxError(f"keyword argument repeated: {key}"))
k.update(kwargs)
if ((num_required_args <= (length := len(a))
or length >= num_pargs and {*code.co_varnames[length:start_kwargs - 1]} < k_keys)
and required_kwargs <= k_keys
and (not (args or kwargs) if has_arbitrary else True)):
return func(*a, **k)
return wrapper
return wrapper
@wait_args
def func(a, *b, c):
print((a + sum(b)) * c)
func(1)(2, 3)(c=3)()
func(c=2)(c=3)()
@quartz wave :x: Your eval job has completed with return code 1.
001 | 18
002 | Traceback (most recent call last):
003 | File "<string>", line 44, in <module>
004 | SyntaxError: keyword argument repeated: c
Oh my, what is going on here xD
now supports variable arguments
also "keyword argument repeated" errors
which the original code didn't have
It only works if you call the function the first time it seems?
If you do func(1)(2, 3)(c=3)() twice it doesnt work
yeah we'll have to fix that
Ahh I see it modifies the closure
!e ```py
from sys import _getframe
from dis import opmap
from ctypes import c_char
thanks chilaxan :)
def builtinexc(exc, depth=1):
frame = _getframe(1 + depth)
addr = id(co := frame.f_code.co_code) + bytes.basicsize - 1
mem = (c_char * len(co)).from_address(addr)
mem[frame.f_lasti + 2:frame.f_lasti + 4] = bytes([opmap['RAISE_VARARGS'], 1])
return exc
def wait_args(func):
num_pargs = (code := func.code).co_posonlyargcount
num_nonkwargs = code.co_argcount
num_nargs = num_nonkwargs - num_pargs
num_kwargs = code.co_kwonlyargcount
num_required_args = num_nonkwargs - (len(func.defaults) if func.defaults else 0)
start_kwargs = num_nargs + (not not code.co_flags & 4) + 1
required_kwargs = {x for x in code.co_varnames[start_kwargs:start_kwargs + num_kwargs]
if x not in func.kwdefaults} if func.kwdefaults else {*()}
has_arbitrary = code.co_flags & 12
a = []
k = {}
k_keys = k.keys()
def wrapper(*args, **kwargs):
a.extend(args)
for key in kwargs:
if key in k:
return builtinexc(SyntaxError(f"keyword argument repeated: {key}"))
k.update(kwargs)
if ((num_required_args <= (length := len(a))
or length >= num_pargs and {*code.co_varnames[length:start_kwargs - 1]} < k_keys)
and required_kwargs <= k_keys
and (not (args or kwargs) if has_arbitrary else True)):
res = func(*a, **k)
a.clear()
k.clear()
return res
return wrapper
return wrapper
@wait_args
def func(a, *b, c):
print((a + sum(b)) * c)
func(1)(2, 3)(c=4)()
func(2)(4, 6)(c=8)()
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
001 | 24
002 | 96
why do people use argspec or inspect they're much more complicated than just doing it by hand
Oh wow, that is significantly faster then returns even with the extra function call
In [24]: %timeit normal(1, 2, 3, c=4)
293 ns Β± 63.2 ns per loop (mean Β± std. dev. of 7 runs, 1000000 loops each)
In [23]: %timeit returns(1)(2, 3)(c=4)
53.3 Β΅s Β± 22.2 Β΅s per loop (mean Β± std. dev. of 7 runs, 10000 loops each)
In [25]: %timeit func(1)(2, 3)(c=4)()
2.74 Β΅s Β± 650 ns per loop (mean Β± std. dev. of 7 runs, 100000 loops each)
it's probably because i straight up just used the code object
also does returns have that error when you repeat keyword arguments in different calls
dem
Neat! Do you mind explaining what the builtinexc stuff does?
!e Apropos of nothing, recently discovered b85decode/encode which makes this technique (exec'ing compressed code) a bit more efficient:
(i:=__import__,exec(i('gzip').decompress(i('base64').b85decode('ABzY89utdV00VVY$!^;)5WVXw1}V^xjw94TPDWfbhoI;+DS9ysf|jV5kVL5@Roe~x?;S3Z<)s1y*|WTv_c)wFH#L~O0a>?=w!q$nEi|u1QaDd82T#-1ybadO?prZ9GL~()PLfYxH(ZqlvW=|xjw_hcBo_s&J6TzaQFP9Ybq-7IEwo&Y|+8Z3^L$qep74D|s#&o%mGPO=8(i;$2OENgO+W{v++Oj+-(FezheZe(WUU%?pM!^~sUqDBZ3T7?NzLLnNZspG?31z`+vU)skn`#KdjRwDkx{M_=mLQr3pEWJF-+t=qGZ!hfE^Xv2L_qW^C6lSY{sD<sc0u&(eqHMXejO%wpicV!w3)R)Ebw=MT^74GqkF?xh#;9Z5Hl|V49s{$cQ+7yIjViY>y;tWlC<dG++#hQXkr!Cy_G(!zes@xfoc#xxIJF}Sq|Up_8e{^pfD0>#$_V%pG&7cKdu-#_{T&e1Sa5IOTTyXze1=Ci3bQDA>}x>y*g?@~*nw0-;vcRR9;;c7tIbbJ-;Ly0dFU$-vf25L5IfQ;w?|@!5#6yp5dN4Ddho~_ZcxXyw3_SvNc*1O>>*qVbS*<Kr6U%SOIC`#BU+~J2MIFzanrnQg(efnVG5H;U=!!gBc@_!h02My4`!zqVmVe(n&gai@10*L6K8&O|KIk?^4*KpjV8qnW^Nmu1HyK-P!<zf!L7*W@PWR=4L$Zzrd^w(kHp54Q3r%vj^We7&)vJ-xI5$~kdM&D4-$-lUl*er$W@NVaxo<#^mIOO%d8IY6y?9H;-Jol5&H|_SEK!S`;&0(Maquq>3I0r`KdcW>8bj-&LC_KJaK>Ar(N+hs|45N)LLG(##2Pd<jfR@D!F1xz6}e`uRGt0>tsEJe%rNLDoY5*`(?VCtSQCKoYCYT$yV?elm-9*'))))
func(1)(2, 3)(c=4)()
func(2)(4, 6)(c=8)()
@verbal talon :white_check_mark: Your eval job has completed with return code 0.
001 | 24
002 | 96
makes it look like a builtin exception raise
!e ```py
int('a')
@quartz wave :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | ValueError: invalid literal for int() with base 10: 'a'
!e ```py
from sys import _getframe
from dis import opmap
from ctypes import c_char
def builtinexc(exc, depth=1):
frame = _getframe(1 + depth)
addr = id(co := frame.f_code.co_code) + bytes.basicsize - 1
mem = (c_char * len(co)).from_address(addr)
mem[frame.f_lasti + 2:frame.f_lasti + 4] = bytes([opmap['RAISE_VARARGS'], 1])
return exc
builtinexc(ValueError("invalid literal for int() with base 10: 'a'"), 0)
@quartz wave :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 11, in <module>
003 | ValueError: invalid literal for int() with base 10: 'a'
Gotcha
!e For comparison
raise ValueError("invalid literal for int() with base 10: 'a'")
@verbal talon :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | ValueError: invalid literal for int() with base 10: 'a'
yeah well not a good comparison because it's the same thing at 0 depth
I'm thinking of a conditional override wrapper for boilerplate overrides so that I don't have to look at else:super().__getattribute__(name) all day
!e ```py
def conditional_override(cond=lambda s,*a,**k:True):
def outer(method):
def inner(self, *args, **kwargs):
if cond(self, *args, **kwargs):return method(self, *args, **kwargs)
else:return getattr(super(),method.name)(*args,**kwargs)
return inner
return outer
@type.call
class c:
"""World!"""
switch = 0
@conditional_override(lambda s,*a:object.getattribute(s,'switch'))
def getattribute(self, name):
print(name);return self
def pos(self):
self.switch=1&object.getattribute(self,'switch')
return self
+c;+c.Hello;print(c.doc)
@floral meteor :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 20, in <module>
003 | File "<string>", line 5, in inner
004 | RuntimeError: super(): __class__ cell not found
Alright finally a worthy opponent: RuntimeError
how does it not find __class__ cell if i give the inner to the class before it's constructed?
I like your funny words magic man
What if I told you my database data is also python code?
Don't need sql when I can just do this:
class database:
def __init__(self, filename):self.fn = filename;self.d = {}
def __getattribute__(self,name):
if name==name.upper():return self.d.get(name,None)
else:return super().__getattribute__(name)
def __setattr__(self, name, value):
if name==name.upper():self.d|={name:value}
else:super().__setattr__(name, value)
def load(self,override={}):
with open(self.fn,'r')as file:
for line in file.readlines():
name, _, value = line.partition("=")
if _:self.d|={name:eval(value)}
self.d|=override;return self.d
def save(self,new_data={}):
self.d|=new_data;s=""
for name, value in self.d.items():s+=f"{name}={value!r}\n"
with open(self.fn,'w')as file:file.write(s.rstrip())
return self
def update(self, data={}):return self.save(data).load()
why not set those functions as lambdas inside init
to which snippet are you referring to, and within that, which functions did you want lambdized?
this
guys check out this cursed one liner golf i made to find the closest prime to a number
!e
cp=lambda n:cp.__dict__.__setitem__("p",lambda n:n>=2 and not any(i for i in range(3,int(n**.5)+1,2)if not n%i))or next([n+o,n-o][cp.p(n-o)]for o in range(3,int(n**.5)+1,2)if cp.p(n+o)|cp.p(n-o))
print(cp(100))
@fair quartz :white_check_mark: Your eval job has completed with return code 0.
97
well I could, I would have to use object.__getattribute__(self, name) instead of super().__getattribute__(name)
super() is kinda too magicky
true
working version in 3.11+ because changes to the structure of the code object broke it ```py
from sys import _getframe
from dis import opmap
from ctypes import c_char
def builtinexc(exc, depth=1):
frame = _getframe(1 + depth)
addr = id(co := frame.f_code) + type(co).basicsize
mem = (c_char * len(co._co_code_adaptive)).from_address(addr)
mem[frame.f_lasti + 2:frame.f_lasti + 4] = bytes([opmap['RAISE_VARARGS'], 1])
return exc
everything shoved in __init__ gonna need some dodgy hacks
!e
cp=lambda n:cp.__dict__.__setitem__("p",lambda n:n>=2 and not any(i for i in range(3,int(n**.5)+1,2)if not n%i))or next([n+o,n-o][cp.p(n-o)]for o in range(3,int(n**.5)+1,2)if cp.p(n+o)|cp.p(n-o))
print(cp(12))
@wheat river :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | File "<string>", line 1, in <lambda>
004 | StopIteration
it could work on lower nums too
!e
cp=lambda n:cp.__dict__.__setitem__("p",lambda n:n>=2 and not any(i for i in range(3,int(n**.5)+1,2)if not n%i))or next([n+o,n-o][cp.p(n-o)]for o in range(3,n,2)if cp.p(n+o)|cp.p(n-o))
print(cp(6543132154))
if we remove some optimisation
@fair quartz :white_check_mark: Your eval job has completed with return code 0.
6543132143
was makin a random rgb generator here
change the range from 3, n, 2 to 1, n, 2
no idea what to use to get the generator to be used
!e
((globals().__setitem__('randint', __import__('random').randint))),list(((print(randint(0,266),",",end=""))for _ in range(3)))
@bronze merlin :white_check_mark: Your eval job has completed with return code 0.
253 ,95 ,9 ,
the blank 1 is
[None, (None, None, None)]
in my terminal
133 ,123 ,192 ,(None, [None, None, None])
!e
print(*[__import__('random').randint(0,255)for _ in[0]*3],sep=', ')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
197, 211, 49
i was lookin for a way
to use generator obj
without it returning True, False, None
liek this humiliating thing
!e
print(*[__import__('random').randint(0,255)for _ in[0]*3],sep=', ')
print(', '.join(map(str,[__import__('random').randint(0,255)for _ in[0]*3])))
grape
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 135, 49, 226
002 | 156, 46, 213
!e ```py
print(*eval('import("random").randint(0,255),'*3),sep=", ")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
211, 25, 162
didn't think i was gonna beat this
good
!e
print(*[__import__('time').time_ns()%256for _ in[0]*3],sep=', ')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
168, 40, 218
!e
print(*eval('__import__("time").time_ns()%256,'*3),sep=", ")
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
127, 33, 111
3 chars shorter than your
but thats not fair
!e
print(f'{id(1)%256}, {id(2)%256}, {id(3)%256}')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
240, 16, 48
!e
print(f'{id("a")%256}, {id("b")%256}, {id("c")%256}')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
176, 48, 240
running that just seems to output 176 for all on my machine though
!e
print(*map(lambda x:id(x)//256%256,('a','b','c')),sep=', ')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
226, 8, 192
thats bad
mhmm
!e
print(*map(lambda x:hash(str(x))%256,(id,int,len)),sep=', ')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
187, 172, 48
!e
print(*map(lambda x:hash(str(x))%256,(id,int,len)),sep=', ')
print(*map(lambda x:hash(str(x))%256,(id,int,len)),sep=', ')
print(*map(lambda x:hash(str(x))%256,(id,int,len)),sep=', ')
print(*map(lambda x:hash(str(x))%256,(id,int,len)),sep=', ')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 46, 33, 104
002 | 46, 33, 104
003 | 46, 33, 104
004 | 46, 33, 104
i give up, thats the shortest code
found something that tied with this: ```py
print(*eval('ord(import("os").urandom(1)),'*3),sep=", ")
!e IMO bitshift operator priority is very weird
# i want to get 255 using bitshift
# that doesnt work
print(-1+1<<8)
print(1<<8-1)
# but with parens its ok
print((1<<8)-1)
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 0
002 | 128
003 | 255
!e ```py
print(*eval('import("os").urandom(1)[0],'*3),sep=", ")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
162, 39, 203
there
it's a bytes object
!e ```py
print(*eval('import("os").urandom(1)[0],'*3),sep=", ")
print(*eval('import("time").time_ns()%256,'*3),sep=", ")
print(*eval('import("random").randint(0,255),'*3),sep=", ")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
001 | 86, 79, 210
002 | 58, 0, 218
003 | 43, 82, 28
ye
!e
print(*__import__("os").urandom(3),sep=", ")
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
176, 87, 185
even smaller
damn
!e ```py
import os;print(os.urandom(3),sep=", ")
print(import("os").urandom(3),sep=", ")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
001 | 98, 120, 68
002 | 237, 254, 11
damnnnnnnnnnnnnnnnnnnn
there's no way it can get shorter right-
lmao
!e ```py
#esoteric-python message
((globals().setitem('randint', import('random').randint))),list(((print(randint(0,255),",",end=""))for _ in range(3)))
#esoteric-python message
print(', '.join(map(str,[import('random').randint(0,255)for _ in[0]*3])))
#esoteric-python message
print(*[import('random').randint(0,255)for _ in[0]*3],sep=', ')
#esoteric-python message
print(*[import('time').time_ns()%256for _ in[0]*3],sep=', ')
#esoteric-python message
print(*eval('import("random").randint(0,255),'*3),sep=", ")
#esoteric-python message
print(*eval('import("time").time_ns()%256,'*3),sep=", ")
#esoteric-python message
print(*eval('ord(import("os").urandom(1)),'*3),sep=", ")
#esoteric-python message
print(*eval('import("os").urandom(1)[0],'*3),sep=", ")
#esoteric-python message
print(*import("os").urandom(3),sep=", ")
#esoteric-python message
import os;print(*os.urandom(3),sep=", ")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
001 | 125 ,201 ,29 ,10, 253, 13
002 | 166, 165, 71
003 | 165, 221, 247
004 | 147, 104, 94
005 | 168, 122, 138
006 | 247, 139, 29
007 | 195, 8, 117
008 | 229, 127, 25
009 | 194, 93, 80
.bm
i did not know there was a bookmark feature
!e random also has randbytes ```py
import random;print(*random.randbytes(3),sep=", ")
import os;print(*os.urandom(3),sep=", ")
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
001 | 87, 123, 128
002 | 48, 222, 23
but why use randbytes when there's urandom
yeah
is there any resource for pointer hacking stuff in cpython using id (and ctypes iirc)?
read about CAPI and object structure
a good resource to know about the offsets is the cpython source itself
do i need to 
any specific files you could direct me to?
there are different files for different objects
ye, any one of them works, i'll figure out the rest if it's structured ig
keep in mind: offset of the field after PyObject_HEAD is object.__basicsize__
offset of the field after PyObject_VAR_HEAD is object.__basicsize__ + tuple.__itemsize__
also tuple.__itemsize__ is always equal to a pointer's size
>>> sys.getsizeof(None)
16
>>> sys.getsizeof(...)
16
>>> sys.getsizeof(0)
24
>>> sys.getsizeof(False)
24
>>> sys.getsizeof(b'')
33
>>> sys.getsizeof('')
51
>>> sys.getsizeof(bytearray())
56
>>> sys.getsizeof(())
40
>>> sys.getsizeof([])
56
>>> sys.getsizeof({})
64
>>> sys.getsizeof({0:0})
232
>>> sys.getsizeof(set())
216
>>> sys.getsizeof(frozenset())
216
>>> sys.getsizeof(set([0,]))
216
>>> sys.getsizeof(frozenset([0,]))
216
sys.getsizeof(0) == int.__basicsize__ == <offset of the digit array in ints>
you mean an empty set right
size of mappingproxy ```py
sys.getsizeof(int.dict)
40
uhhh there's a lot i need to learn
>>> sys.getsizeof(int)
408
>>> sys.getsizeof(bool)
408
>>> sys.getsizeof(list)
408
>>> sys.getsizeof(sys)
72
>>> sys.getsizeof(sys.getsizeof)
72
>>> sys.getsizeof(len)
72
>>> sys.getsizeof(type('',(),{}))
1_072
>>> sys.getsizeof(type('',(),{})())
48
>>> sys.getsizeof(type('',(),{'__slots__':()})())
32
why does int have a __dict__ but an int object doesn't...
int.__dict__ is a mappingproxy of dictionary of type int
instances of int doesnt have .__dict__
is it possible to do smth like that with pure python classes? declaring a class method which instances don't get?
https://docs.python.org/3.11/library/functions.html#type
The dict dictionary contains attribute and method definitions for the class body; it may be copied or wrapped before becoming the
__dict__attribute.
yes, use metaclasses
!e
class Meta(type):
def some_meth(cls):
print('hello there')
class Type(metaclass=Meta):
...
instance = Type()
Meta.some_meth(Type)
Type.some_meth()
instance.some_meth()
@fleet bridge :x: Your eval job has completed with return code 1.
001 | hello there
002 | hello there
003 | Traceback (most recent call last):
004 | File "<string>", line 12, in <module>
005 | AttributeError: 'Type' object has no attribute 'some_meth'
__dict__ descriptor is defined in type class
and if you do some_class.__dict__ then this descriptor is called to give you value
!e
from pprint import pprint
pprint(type.__dict__['__dict__'].__get__(int))
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | mappingproxy({'__abs__': <slot wrapper '__abs__' of 'int' objects>,
002 | '__add__': <slot wrapper '__add__' of 'int' objects>,
003 | '__and__': <slot wrapper '__and__' of 'int' objects>,
004 | '__bool__': <slot wrapper '__bool__' of 'int' objects>,
005 | '__ceil__': <method '__ceil__' of 'int' objects>,
006 | '__divmod__': <slot wrapper '__divmod__' of 'int' objects>,
007 | '__doc__': 'int([x]) -> integer\n'
008 | 'int(x, base=10) -> integer\n'
009 | '\n'
010 | 'Convert a number or string to an integer, or return '
011 | '0 if no arguments\n'
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ujibejupur.txt?noredirect
>>> '__dict__' in int.__dict__
False
>>> '__dict__' in type.__dict__
True
Thx for the obfuscation tip
I was working on a Python interpreter but holy hell the type structure is hell to implement
type as in type or type as in all the types?
Probably the entire type system in Python
yeah, runtime mutable types of types ... are quite annoying to get right
how to convert pyobject pointer to python obejct?
ctypes.py_object.from_address(id(None)).value dont work
obj = ...
ptr = id(obj)
add_some_reference(obj) # to keep obj alive
del obj
# now i want to get `obj`
obj = ctypes.py_object.from_address(ptr).value
Dunno what a proper way would be but you can make a list/tuple with a single element and replace it's address in the list with the one you want to get
ctypes.cast(id(object), ctypes.py_object).value
assuming id/address is all you have
otherwise ctypes.py_object(object) will work too
!e ```py
from _ctypes import PyObj_FromPtr, Py_INCREF
obj = "abc"
ptr = id(obj)
Py_INCREF(obj)
del obj
obj = PyObj_FromPtr(ptr)
print(obj)
@quartz wave :white_check_mark: Your eval job has completed with return code 0.
abc
thank you
i will use that
this is more esoteric)
yeah exactly this, I had a lot of things already implemented but then I realized I needed to support the type system and copying the cpython impl is kinda difficult in kotlin considering you have to deal with kotlin classes as well
it's not like it's impossible but it's definitely a big challenge
I remember working on one with Fuyu back in the day but that ended up not going anywhere and I can't reuse code since it's GPL and I want my code to be 100% BSD3
I can tell you that you can't use java types as python types, you need a type field (though you probably figured that out by now)
print((2645608968347327576478451524936).to_bytes((True<<True<<True<<True) | (True<<True<<True) | (True<<False), 'little').decode())
!e ```py
print((2645608968347327576478451524936).to_bytes((True<<True<<True<<True) | (True<<True<<True) | (True<<False), 'little').decode())
@sick hound :white_check_mark: Your eval job has completed with return code 0.
Hello, world!
That's nuts
n x n tictactoe
ttt=lambda n:(((lambda a:a(a))(lambda g:lambda e,r,o,t,b,w:((print(o[t[0]],"'s turn!"),(lambda i:i(i))(lambda _:((lambda m:(0if m and[b.__setitem__(q,t[0])for q in((*map(int,m.groups()),),)if all(0<=x<n for x in q)and b[q]==-1]else _(_)))(r.match(r'(\d+), (\d+)',input("Coords? "))))),(print(),[[print(*[o[i]for i in w])]for w in b]),t.reverse(),print(o[t[1]],'Won!')if any((any(w(m)for m in b),any(w(m)for m in e.rot90(b)),(w(b.diagonal())),w(e.rot90(b).diagonal())))else print('Nobody Won!')if e.all(b!=-1)else g(g)(e,r,o,t,b,w))))))(*(lambda e:(e,__import__('re'),{0:'x',1:'o',-1:' '},[0,1],e.zeros((n,n))-1,lambda h:e.all(h==h[0])and h[0]!=-1))(__import__('numpy')))
!e
for a in i:
for b in i:
for c in i:
for x in j:
for y in j:
for z in j:
for k in range(50):
for l in range(50):
for m in range(50):
if (k*a)**x+(l*b)**y==(m*c)**z:
if k>0:
if l>0:
if m>0:
print(str(a*k)+eval(r'"\u00b' + str(x) + '"')+'+'+str(b*l)+eval(r'"\u00b' + str(y) + '"')+'='+str(c*m)+eval(r'"\u00b' + str(z) + '"'))
@violet rune :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | NameError: name 'i' is not defined. Did you mean: 'id'?
for a in i:
for b in i:
for c in i:
for x in j:
for y in j:
for z in j:
for k in range(50):
for l in range(50):
for m in range(50):
!e Depends on i. Maybe it's just an alternative slice notation:
def skip_first_three(i):
for a in i:
for b in i:
for c in i:
for d in i:
yield d
print(*skip_first_three(iter([0, 1, 2, 3, 4, 5, 6, 7])))
@restive void :white_check_mark: Your eval job has completed with return code 0.
3 4 5 6 7
!e
def f1() -> None:
g()
def f2() -> None:
return g()
from dis import dis
dis(f1)
print('-'*30)
dis(f2)
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 2 0 LOAD_GLOBAL 0 (g)
002 | 2 CALL_FUNCTION 0
003 | 4 POP_TOP
004 | 6 LOAD_CONST 0 (None)
005 | 8 RETURN_VALUE
006 | ------------------------------
007 | 4 0 LOAD_GLOBAL 0 (g)
008 | 2 CALL_FUNCTION 0
009 | 4 RETURN_VALUE
if you dont care what is returned, second way is two instructions faster (POP_TOP and LOAD_CONST)
yes but it'll POP_TOP when the value is ignored anyway
so it's only one instruction faster
also one instruction faster when you assign it to a throwaway value
it'll POP_TOP anyway, so it is same on caller side, and its two instructions faster inside called function