#esoteric-python
1 messages · Page 66 of 1
None: True.__dir__().__class__().sort()
nice
reckon there's a way to get Ellipsis? i believe it's only referenced a couple times in the standard library. i think for sure that's gonna be the hardest one if we try for it.
lets get the rest of them first lol
>>> ....__class__
<class 'ellipsis'>
>>>
this is still trippy to type :D
in the standard library, pretty much fuck-all. it's used to represent a list that contains itself. it's also very common in numpy for array indexing
!eval ```py
a = []
a.append(a)
print(a)
@brisk zenith Your eval job has completed.
[[...]]
oh for printing recursive stuff out?
i'm not sure if it actually uses an ellipsis object for that and if there's any way to get it from that, but i've heard that python2 crashed when you printed a list containing itself cause ellipsis wasn't a thing then
yeah, it works for tuples too. (don't ask how you get a tuple inside of itself :D)
short answer: ctypes.pythonapi.PyTuple_SetItem
ah. ctypes
long answer: ```py
from ctypes import c_void_p,c_ssize_t,pythonapi
a = (0,)
pythonapi.PyTuple_SetItem(c_void_p(id(a)),c_ssize_t(0),c_void_p(id(a)))
a
((...),)
a[0] is a
True
the magic wand of python
code stolen from @pine edge
but yeah, PyTuple_SetItem is used internally when building tuples from literals, for example. they don't just appear out of nowhere after all.
just so happens that it's a public function in the pythonapi :D
nice
i'm pretty sure you can then pickle, then restore that fucked up tuple
sounds reasonable enough. wonder what the __reduce__ method of these types looks like
would be interesting to see if they handle it specially or if it just seems to work
i'm betting on the latter
>>> a = (0,)
>>> pythonapi.PyTuple_SetItem(c_void_p(id(a)),c_ssize_t(0),c_void_p(id(a)))
0
>>> a
((...),)
>>> a.__reduce__
<built-in method __reduce__ of tuple object at 0x030F8690>
>>> a.__reduce__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\chilaxan\AppData\Local\Programs\Python\Python37-32\lib\copyreg.py", line 65, in _reduce_ex
raise TypeError("can't pickle %s objects" % base.__name__)
TypeError: can't pickle tuple objects
>>>```
huh
>>> import pickle
>>> pickle.dumps(())
b'\x80\x03).'
>>>
>>> import pickle
>>> pickle.dumps(())
b'\x80\x03).'
>>> from ctypes import c_void_p,c_ssize_t,pythonapi
>>> a = (0,)
>>> pythonapi.PyTuple_SetItem(c_void_p(id(a)),c_ssize_t(0),c_void_p(id(a)))
0
>>> pickle.dumps(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while pickling an object
>>>
fascinating :D
thats weird
i just found a builtin so mysterious that i've never heard of
in 3.7.2, object.__subclasses__()[45]
PyCapsule
Capsule objects let you wrap a C "void *" pointer in a Python
object. They´re a way of passing data through the Python interpreter
without creating your own custom type.
Capsules are used for communication between extension modules.
They provide a way for an extension module to export a C interface
to other extension modules, so that extension modules can use the
Python import mechanism to link to one another.
TIL
@brisk zenith do you think you could do anything tricky with it?
well, you can't make instances of it, but i'll look up how to use it.
of course i've never seen it, i haven't read through the entire c-api docs yet
wow that makes me actually seem like i try to be relatively smart
hahaha
when in fact i just procrastinate actually being smart
exams in a month? nah, ctypes and segfaults.
👌
hey ive got finals soon to
here's an interesting: golfed segfault
wow i'm a new breed of tired, "here's an interesting"
nah it's good i've got people to talk to
nevermind then
:D
__import__("ctypes").string_at(0)
this is, i suppose, the naïve first approach. it's hella short but could it be shorter? maybe.
prob
haha
import os;os.kill(os.getpid(),11)
exact same length
but i don't count that as being a valid attempt as it's not a true segfault
true
it's telling the interpreter that it's segfaulted and should probably fuck off, rather than actually segfaulting
quote of the day right there
thank you
when i'm tired my vernacular comes out and i use a lot of colourful language :D
btw your first one didnt segfault my interpreter
>>> __import__("ctypes").string_at(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\chilaxan\AppData\Local\Programs\Python\Python37-32\lib\ctypes\__init__.py", line 497, in string_at
return _string_at(ptr, size)
OSError: exception: access violation reading 0x00000000
>>>```
the wonders of windows
didnt crash the interpreter tho lol
doesn't matter, still a segfault :D
aight lol
if we wanted to crash the interp-- wait no that would crash the entire computer
i suppose crashing the computer would also crash the interpreter :D
absolutely :D
but let's not post any of those here haha
straying away from #esoteric-python to #esoteric-morals
now that sounds like an otname
haha
true
@brisk zenith yo do you want to continue getting all the classes from True?
sure in a bit, just gonna hop into bed and procrastinate sleeping. give me a moment :D
well then what's stopping us from doing what we did yesterday?
i think one True is a good restriction
we cant use forloops
i wanna see how far we can get first :D
bool: True.__class__
int: True.__class__.__base__
str: True.__doc__.__class__
float: True.__float__().__class__
object: True.__class__.__base__.__base__
tuple: True.__class__.__bases__.__class__
list: True.__dir__().__class__
bytes: True.__doc__.encode().__class__
# not types but still significant bits and bobs:
False: True.imag.__bool__()
NotImplemented: True.__subclasshook__()
None: True.__dir__().__class__().sort()
complex
set
frozenset
dict
module
function
method
code
we still need these from our original list then
nice
@brisk zenith tbh we should get NoneType instead of None
True.__class__.__class__ -> type
import ctyes as c;c.string_at(0) @brisk zenith made it shorter 😛
nevermind I can't spell
Oh, and dict is True.__class__.__prepare__().__class__
Are we trying to golf this?
Are we trying to get every builtin from True?
>>> True.__class__.__class__(True.__repr__(), True.__class__.__bases__, True.__class__.__prepare__())
<class '__main__.True'>```
Custom classes: check
I doubt we can get a function/method tho
With result we also can't get code/module
Actually
Nvm, True.__class__.__class__.mro.__class__ said method but it's a method_descriptor
True.__class__.__dict__.__class__ for mappingproxy
I don't think we can use more than one True
And we only care about the main builtins
Trying to use these to get others :p
I made a test script that I hope checks every possibility. Any class not in {'dict', 'bool', 'list_reverseiterator', 'int', 'builtin_function_or_method', 'bytes', 'str_iterator', 'tuple_iterator', 'str', 'method_descriptor', 'NotImplementedType', 'method-wrapper', 'list', 'object', 'mappingproxy', 'wrapper_descriptor', 'list_iterator', 'type', 'tuple', 'NoneType'} takes at least two attribute accesses.
If anyone wants to use my terrible quality code, ```python
unchecked = [True]
checked = []
checked_classes = []
def thorough_dir(cls):
#creates a list of attributes a class implements
#does not support arbitrary objects, only types
#unlike dir(), does not sort the results
#(stolen from another project which is why it has comments)
attributes_found = []
all_superclasses = cls.mro
for superclass in all_superclasses:
#appends the keys of dict to the list
attributes_found += superclass.dict
return attributes_found
for i in range(5):
print(unchecked)
to_check_after = []
for value in unchecked:
print(value)
dir = thorough_dir(value.class)
for attribute in dir:
try:
print("", attribute)
result = value.class.getattribute(value, attribute)
to_check_after.append(result)
if hasattr(result, "call"):
called = result()
to_check_after.append(called)
except Exception as e:
print(i,"!", e)
checked += [value for value
in unchecked
if value not in checked and value.class not in checked_classes]
checked_classes = [obj.class for obj in checked]
unchecked = to_check_after
print({type(x).name for x in checked})``` I'm going to bed.
In order to fudge something, I've done ```py
sys.modules[name] = instance_of_a_class
Is there a way to make that work for from .. import * though?
@desert garden you'd need to mess with __import__
In what way?
Okay, found a bodge that does what I need for this context
I just iterated the object, and anything that didn't start with _ I defined onto builtins
nice
globals() is bound to the module so you'd have to apply it from within the importing code
import * still won't give you bound methods... maybe if you add their names to __all__
I just did ```py
def apply(object):
import builtins
for i in dir(object):
if i.startswith('_'):
continue
setattr(builtins, i, getattr(object, i))
robot = Robot()
apply(robot)
sys.modules[name] = robot
ok i think you're not quite getting what i'm suggesting
Then I can ```py
import robot
enableControls() # Works
robot.enableControls() # Also works
ok wait
maybe you can...
ok if your type is layout-compatible with module (i.e. no __slots__, not a ctypes struct, not a subclass of most built-in types)...
you can do this: ```py
import types
import sys
class RobotModule(types.ModuleType):
def new(self):
raise Exception("RobotModule type not intended to be used this way")
def enableControls(self):
print("enabled controls")
_self = sys.modules[name]
self.class = RobotModule
for method in dir(RobotModule):
if not method.startswith(''):
globals()[method] = getattr(_self, method)
then you can do py from robot import * enableControls()
you can also simply add enableControls to __all__
actually, adding it to __all__ works in all cases for import *, e.g. ```py
import sys
class RobotModule:
def init(self):
self.all = ['enableControls']
def enableControls(self):
print("enabled controls")
_self = sys.modules[name] = RobotModule()
making the instance the real module (if it is compatible with the module type), or sharing its __dict__ with globals() (for any other type) would be a viable way to get other top-level things defined in the file to show up.
if you do define __all__ you'd need to add all of the other names to it as well
import sys
class RobotModule:
def __init__(self):
self.__dict__ = globals()
def enableControls(self):
pass
def global_function():
pass
_self = sys.modules[__name__] = RobotModule()
__all__ = [x for x in dir(_self) if not x.startswith('_')]
@desert garden any thoughts?
Oh right, I see what you mean
In that second one, would global_function be exported too?
yes
I don't want that, but I take it the first one doesn't?
well
if you don't want it you could define it with an _
or have an explicit __all__ that doesn't include it
tbh the normal way to do what you're trying to do is probably to simply define __all__ with the names you want, and define them all at the top level. A custom module class is normally only used if you want to be able to do e.g. operator overload on the module (to be able to treat a single-function module like a function, for example)
Yeah, I'm pretty sure what I'm doing is a horrible anti-pattern 😄
Said robot object then has stuff like robot.drive(left, right), robot.reverse(robot.left), etc., and I'm just trying to avoid having a load of globals to store state
ok well
what i might do in that case is
see what you're doing right now limits you to one robot object, so you don't really get the benefit of not having globals
hold on
Something like this... ```py
import sys
class Robot:
def init(self):
self.dict = globals()
def drive(self, direction):
pass
def reverse(self, direction):
pass
def enableControls(self):
pass
# etc
_default_instance = Robot()
def wrap(methodname):
return getattr(_default_instance, methodname)
for methodname in dir(deault_instance):
if methodname.startswith(''):
continue
globals()[methodname] = wrap(methodname)
Then you *can* create an instance of the class, or you can just use the ones from the module and they'll be from the default instance
Given that the robot refers to a literal hardware robot connected to the raspberry pi running it over GPIO, I don't have any plans to support more than one at once 
ah
does anyone know how to parse a long dumped by marshal.dumps?
>>> import marshal
>>> marshal.dumps(10**10)
b'\xec\x03\x00\x00\x00\x00d\x17(\t\x00'
>>> data = _
>>> long_ident = data[:1]
>>> long_data = data[1:]
>>> long_ident, long_data
(b'\xec', b'\x03\x00\x00\x00\x00d\x17(\t\x00')
first byte is datatype identifier
rest is the data
might be related to how python stores ints as chunks of numbers less than 2**15 or 2**30
I looked at the code and it just did bitshifts and bitwise and
Here's how they're encoded https://github.com/python/cpython/blob/master/Python/marshal.c#L173
iirc you can see the longobject struct at /Include/cpython/longintrepr.h
might have comments explaining how they're stored
How marhal parses longs: https://github.com/python/cpython/blob/master/Python/marshal.c#L758
but sadly I cant read C nor are there any comments about it
hmm, what if you try using an int above 2**64?
also sorry @rugged sparrow i fell asleep lmao
@grave rover don't you mean this is the implementation of encoding a pylong? https://github.com/python/cpython/blob/master/Python/marshal.c#L227
are you trying to encode or decode?
Trying to decode
Also can't open that cause it crashes phone
Basically what I need is some_function(long_bytes) -> value
let's start with simple integers: ```py
b'\xe9\x00\x00\x00\x00' # marshal.dumps(0)
---- ---------------
size int value
---- ---------------
b'\xe9\x01\x00\x00\x00' # marshal.dumps(1)
>>> marshal.dumps((2 ** 31) - 1)
b'\xe9\xff\xff\xff\x7f'
>>> marshal.dumps((2 ** 31))
b'\xec\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00'
>>>
Oh?
I thought they'd be 8-12 bits as described in struct docs
!e ```py
import marshal
print(marshal.dumps(2 << 2048))
@brisk zenith Your eval job has completed.
b'\xec\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
... (truncated - too long)
Full output: https://paste.pythondiscord.com/pogucukixe
!e `import struct; print(struct.unpack("i", b"\x89\x00\x00\x00"))
Sorry, but you may only use this command within #bot-commands.
:(
\x89\x00\x00\x00 is likely the size
I'd expect it to be two, and have the actual data be a multiple of 4/8
the first 5 bytes are type and size
so we can ignore those
the size of that int is apparently \x89 which is 137
the amount of bytes after the size is 274
137 * 2
/* We assume that Python ints are stored internally in base some power of
2**15; for the sake of portability we'll always read and write them in base
exactly 2**15. */
aha, as i suspected
Wat
which is why the length of the integer bytes on a 64 bit python is double the given size as i mentioned
on 64-bit machines a python integer is stored internally as chunks of less than 2**30
on 32 bit, that's 2 ** 15
Hm
So 10**25 would be either (0, 5120, 1313, 12448, 22865, 264) if using 6H or (0, 0, 0, 20, 33, 5, 160, 48, 81, 89, 8, 1) if using 12B
not sure
so, the value of python integers are stored as an array of C ints internally, yeah?
the marshal code constructs the pyobject by writing to that array. we can't do that without a bit of fuckery.
actually that's the wrong link maybe
(wow i'm tired) but yeah, you need to figure out how to get the value of that array as a python integer.
basically, python integers are far more complicated than you'd expect and probably requires quite a bit of strong brainthink
as for the marshalled bytes, that looks like an array of C shorts, perhaps.
@brisk zenith it's all good
Six shorts it is then
I got it 
I've got an environment that's had del __builtins__.__import__
Is there a way to import anyway?
_ is a filtered char that can't be used
Actually, the whole blacklist is ()[]{}_.#"'\ABCDEFGHIJKLMNOPQRSTUVWXYZ
Looking at it, things like lambda: ... are fine, but there's no way to then call that lambda
If this weren't a challenge to break out of the sandbox I'd want to say that evaling a string after that blacklist is safe, but clearly I'm wrong
that's probably impossible
What's a good way to reverse-engineer data packets from packets and partial expected data format?
Packet log:
are you sure that's #esoteric-python?
@brisk zenith i have a pretty decent challenge for you
make a function makeKeyword(keyWordName,keyWordValue) that returns nothing, but makes a new keyword that has the value given to it in the makeKeyword function that behaves like any keyword in python (like True)
ex: python makeKeyword('hello','hi there') print(hello) #prints hi there hello = 1 #throws an error about assigning to keywords or any error, so long as it isnt successful
its kinda like the Maybe challenge but doesnt have to have a random value
how heavily can you actually hack the production of bytecode? Could you make a keyword that changes, or introduces new functionality, and plays along with the other tokens that are close by? Something like... create a const keyword which would make it so that if you typed const a = 4 - then "a" would be a new keyword like you defined above?
Nah, that doesn't compile properly.
If it gets through syntax processing and is built into the AST, the sky's the limit
As you can see, const: a = 4 would likely be workable because it got through syntax parsing
wha-oh right, annotations
Problem here is that annotations don't carry though into bytecode
yes they do ```py
dis.dis('const: a = 4')
1 0 SETUP_ANNOTATIONS
2 LOAD_CONST 0 (4)
4 STORE_NAME 0 (const)
6 LOAD_NAME 1 (a)
8 STORE_ANNOTATION 0 (const)
10 LOAD_CONST 1 (None)
12 RETURN_VALUE```
I could probably make use of that in BytePatches
Like addAnnotationHandler
It rewrites the code into a LOAD_CONST(4) STORE_NAME(a) instead and runs annotation_funcs["const"]("a", 4, all_func_ops)
It's important to actually dis a function itself because that's the form you're going to be getting your code objects in
i wonder how you get the annotations from that then
you could dis the function source
Thinking about it actually, the more "pythionic" way to do consts would be ```py
a: Const[int] = 5
And embrace the fucking awful type annotation syntax that they decided on
(Sidenote: Which dev looked at that and though "That looks nice, let's use that"??)
probably some C# bellend
how would you have done it instead?
int a = 5
And instead of from typing import List, just modify the standard list object to work as a type annotation
And then probably do list<int> a = 5
from __future__ import annotations kinda solves that
Instead of the hell that is replacing List.__getitem__ and then doing a: List[int] = 5
i thought the future import only allowed postponed evaluation of type annotations
yeah, but then you can do things like a: list[int] apparently
huh
That seems like it would really fuck with a badly written interpreter
Because list.__getitem__ now do two different things
🤷 or I might be wrong, but at least it doesn't complain about it
It never has complained about it
It just doesn't actually work if you use a lower case l
>>> a: list[int]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable
>>> from __future__ import annotations
>>> a: list[int]
>>> a = lambda a: print(a)
>>> a.__annotations__["a"] = str
``` xD
from typing import NamedTuple, NamedTupleMeta
class ComponentTupleMeta(NamedTupleMeta):
def __new__(mcls, typename, bases, ns):
if NamedTuple not in bases:
base = super().__new__(mcls, '_base_' + typename, (NamedTuple,)+bases, ns)
else:
base = super().__new__(mcls, '_base_' + typename, bases, ns)
bases = (base, *(b for b in bases if not isinstance(b, NamedTuple)))
return super(NamedTupleMeta, mcls).__new__(mcls, typename, bases, ns)
def __add__(self, other):
return f'{self.__name__} {other.__name__}'
class Component(metaclass=ComponentTupleMeta):
pass
class Vector(Component):
x: int
y: int
def __add__(self, other):
return Vector(self.x+other.x, self.y+other.y)
a = Vector(1,1)
b = Vector(5,5)
print( (Vector + Vector) )
print( a + b )```
Vector Vector
Vector(x=6, y=6)
there are so many restrictions on what you can do with namedtuple subclasses but i managed to get operator overloads working on sub meta classes of namedtuple
also without having to make stuff like Vector inherit directly from namedtuple or have to specify a metaclass
im taking baby steps towards writing a python vm
so far observing dis results to figure out how the instructions work
and i've already hit a bit of a block
>>> dis.dis("a = 1")
1 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (a)
4 LOAD_CONST 1 (None)
6 RETURN_VALUE
>>> dis.dis("a = 0")
1 0 LOAD_CONST 0 (0)
2 STORE_NAME 0 (a)
4 LOAD_CONST 1 (None)
6 RETURN_VALUE
>>> dis.dis("a = 12")
1 0 LOAD_CONST 0 (12)
2 STORE_NAME 0 (a)
4 LOAD_CONST 1 (None)
6 RETURN_VALUE
>>> dis.dis("a = '12'")
1 0 LOAD_CONST 0 ('12')
2 STORE_NAME 0 (a)
4 LOAD_CONST 1 (None)
6 RETURN_VALUE
>>>
how does LOAD_CONST work in these examples? where are the constants stored? there's nothing in the bytecode that indicates how or why those particular values are the constant at index 0
constants and names are stored on separate attributes of the code object
as tuples
>>> compile('a = 12', '<example>', 'exec').co_consts
(12, None)
>>> compile('a = 0', '<example>', 'exec').co_consts
(0, None)```
those are marshalled
you'd do marshal.loads(pyc_content[16:] i believe
the first 16 bytes are metadata
i think it's 8 or 12 bytes on python versions below 3.7 or something like that
ohhh ok i see. since im gonna forego writing a compiler it's jus gonna work with pycs for now. so i guess ill have to write a marshal deserializer too
(not writing it in python)
ah okay
@grave rover was doing exactly that (but in python) recently
but implementing it himself
cool cool
you can find the marshal source here: https://github.com/python/cpython/blob/master/Python/marshal.c
yeah it's pretty scary haha
ok, i think instead of using pycs ill use some other easier to parse format
maybe some kind of pyc to json translator
interesting.
is there a disassembler for the marshal format like pickletools.dis for pickle?
>>> marshal.loads(b'\xfb\xdb\x00\x00\x00\x00\xda\x01b')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'```
2 0 LOAD_CONST 0 (<code object test at 0x0000024DC36FE030, file "<dis>", line 2>)
2 LOAD_CONST 1 ('test')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (test)
5 8 LOAD_NAME 0 (test)
10 LOAD_CONST 2 ('poop')
12 CALL_FUNCTION 1
14 POP_TOP
16 LOAD_CONST 3 (None)
18 RETURN_VALUE
Disassembly of <code object test at 0x0000024DC36FE030, file "<dis>", line 2>:
3 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('lol')
4 LOAD_FAST 0 (a)
6 LOAD_CONST 2 ('whats up?')
8 CALL_FUNCTION 3
10 POP_TOP
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
dis of this:
test_code = '''
def test(a):
print('lol', a, 'whats up?')
test('poop')
'''
insert yo-dawg xzibit meme here
I can send over my code for it later today
ty, i appreciate it
for now what im doing is this instead of using pycs:
def code_to_json(code: str):
compiled_code = compile(code, '<script>', 'exec')
result = {
'argcount': compiled_code.co_argcount,
'cellvars': compiled_code.co_cellvars,
'code': list(compiled_code.co_code),
'consts': compiled_code.co_consts,
'filename': compiled_code.co_filename,
'firstlineno': compiled_code.co_firstlineno,
'flags': compiled_code.co_flags,
'freevars': compiled_code.co_freevars,
'kwonlyargcount': compiled_code.co_kwonlyargcount,
'lnotab': list(compiled_code.co_lnotab),
'name': compiled_code.co_name,
'names': compiled_code.co_names,
'nlocals': compiled_code.co_nlocals,
'stacksize': compiled_code.co_stacksize,
'varnames': compiled_code.co_varnames
}
return json.dumps(result, indent=4)
but then it turns out you get code objects inside your code objects 😄
wow fun
you certainly do, but i'm pretty sure they're only found in co_consts
so just iterate over that and apply it recursively if you find any code objects there.
you get onto extended arguments
oh geeze
and you can have infinitely many of them in a row if you need to
also, lnotab isn't a list is it? it's a bytes object with special formatting
it's bytes but json cant serialize bytes
yes, but he listified it so it could be jsoned
ye
ah very well
>>> vars
'aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an,ao,ap,aq,ar,(...),zs,zt,zu,zv,zw,zx,zy,zz'
>>> dis.dis(vars)
1 0 LOAD_NAME 0 (aa)
2 LOAD_NAME 1 (ab)
4 LOAD_NAME 2 (ac)
6 LOAD_NAME 3 (ad)
8 LOAD_NAME 4 (ae)
10 LOAD_NAME 5 (af)
12 LOAD_NAME 6 (ag)
# ...
500 LOAD_NAME 250 (ju)
502 LOAD_NAME 251 (jv)
504 LOAD_NAME 252 (jw)
506 LOAD_NAME 253 (jx)
508 LOAD_NAME 254 (jy)
510 LOAD_NAME 255 (jz)
512 EXTENDED_ARG 1
514 LOAD_NAME 256 (ka)
516 EXTENDED_ARG 1
518 LOAD_NAME 257 (kb)
520 EXTENDED_ARG 1
522 LOAD_NAME 258 (kc)
# ...
1524 EXTENDED_ARG 1
1526 LOAD_NAME 509 (tu)
1528 EXTENDED_ARG 1
1530 LOAD_NAME 510 (tv)
1532 EXTENDED_ARG 1
1534 LOAD_NAME 511 (tw)
1536 EXTENDED_ARG 2
1538 LOAD_NAME 512 (tx)
1540 EXTENDED_ARG 2
1542 LOAD_NAME 513 (ty)
1544 EXTENDED_ARG 2
# ...
2164 EXTENDED_ARG 2
2166 LOAD_NAME 669 (zy)
2168 EXTENDED_ARG 2
2170 LOAD_NAME 670 (zz)
2172 EXTENDED_ARG 2
2174 BUILD_TUPLE 671
2176 RETURN_VALUE```
how does that work? o.o
EXTENDED_ARG 2 means it's got 2 extra bytes right?
where are those stored?
ohhhh
you're loading it into the extended arg
i get it
... right?
ok nevermind
third time's the charm
the actual bytes that do that are \x90\x02e\x9d
EXTENDED_ARG 2
LOAD_NAME 157```
so the bytes of the integer for the name that actually gets loaded are 2 157
(2 << 8) + 157 == 669
and 669 is the index of the name to actually load
the EXTENDED_ARG extends the argument of the next instruction
@brazen geyser
where is the code class located? is it possible to import it?
from types import CodeType```
@brazen geyser
it also takes 13 arguments, i'll quickly find out what they are so you don't have to...
co_argcount, co_kwonlyargcount, co_nlocals, co_stacksize, co_flags, co_code, co_consts, co_names, co_varnames, co_filename, co_name, co_firstlineno, co_lnotab
if you want to create one
cheers pastebin 😃
also here's juan's code for "modifying" code objects ```py
def _patch_code(code: CodeType, **kwargs):
"""Create a new CodeType object with modified attributes."""
code_attrs = {}
# Collect the original CodeType attributes
for attr in dir(code):
if "__" not in attr:
code_attrs[attr] = getattr(code, attr)
# Patch the new attributes over the original ones
code_attrs.update(kwargs)
new_object = CodeType(
code_attrs["co_argcount"],
code_attrs["co_kwonlyargcount"],
code_attrs["co_nlocals"],
code_attrs["co_stacksize"],
code_attrs["co_flags"],
code_attrs["co_code"],
code_attrs["co_consts"],
code_attrs["co_names"],
code_attrs["co_varnames"],
code_attrs["co_filename"],
code_attrs["co_name"],
code_attrs["co_firstlineno"],
code_attrs["co_lnotab"]
)
return new_object```
god you must have really searched deep for that, surely.
last time i saw that was with my C++ I/O in python hack
i googled for your C++ I/O in python hack :P
https://www.google.com/search?q=cpp_stdio fourth result
hmm couldnt you do like
import copy
def patch_code(code, **kwargs):
new_code = copy.copy(code)
for key, value in kwargs.items():
setattr(new_code, key, value)
return new_code
ah rip
i wish it was that easy though
my cpystructs stuff would allow you to force it though, but that's a bit too hacky
may as well just create a new object
do read-only attributes prevent access to __dict__ directly too?
__dict__ isn't implemented for code objects anyways, i don't think
>>> (lambda:0).__code__.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'code' object has no attribute '__dict__'```
lame
yeah, the only way i can think of modifying code objects by force is by writing to their memory space
using ctypes or something
but that's not reliable i'd imagine
what if you have more than 65536 locals
doesnt python throw an error at that point
apparently not
well, not locals, but names of accessed globals, as in pastebin's post above
65676 393816 EXTENDED_ARG 1
393818 EXTENDED_ARG 256
393820 LOAD_NAME 65675 (dtdz)
393822 POP_TOP
65677 393824 EXTENDED_ARG 1
393826 EXTENDED_ARG 256
393828 LOAD_NAME 65676 (dtea)
393830 POP_TOP```
(For the record) ```py
az = string.ascii_lowercase
dis.dis('\n'.join([x for x in map(''.join,itertools.product(az,az,az,az)) if x not in ('elif','else','from','with')]))```
should have used uppercase to avoid the keywords 😛 oh well
yeah pastebean showed me the same sort of thing a while ago
DUP_TOP
Duplicates the reference on top of the stack.
New in version 3.2.
DUP_TOP_TWO
Duplicates the two references on top of the stack, leaving them in the same order.
New in version 3.2.
bit confued about these two
wouldn't dup_top already leave them in the same order?
or does it place the duplicate before the original?
oh, the two references on top of the stack
nvm, i can't read 😄
case TARGET(DUP_TOP): {
PyObject *top = TOP();
Py_INCREF(top);
PUSH(top);
FAST_DISPATCH();
}
case TARGET(DUP_TOP_TWO): {
PyObject *top = TOP();
PyObject *second = SECOND();
Py_INCREF(top);
Py_INCREF(second);
STACK_GROW(2);
SET_TOP(top);
SET_SECOND(second);
FAST_DISPATCH();
}
nice, which file are these in?
ceval.c => evaluation
yup
compile.c => bytecode compilation
dup_top_two is like "pick 2nd item" twice [i don't know if the python stack has an nth item operation]
@brisk zenith as Larry said "a big for loop that iterates over instructions 😄 "
switch/cases are nice and simple. no need to overcomplicate this
Python also uses Labels as values if
the compiler is GCC
it is faster than this for loop thingy
Using the GNU Compiler Collection (GCC): Labels as Values
apparently python used to have a DUP_TOPX instruction, that DUP_TOP and DUP_TOP_TWO replaced because nothing else was ever used
well.. the python bytecode instructions are crazy long 😄
Larry Hastings Ever wondered how CPython actually works internally? This talk will show you. We start with a simple Python program, then slowly step through ...
why is ceval_gil just a header file
This cool to if you want to know more about
interesting, thanks
/* XXX TO DO:
XXX speed up searching for keywords by using a dictionary
XXX document it!
*/
at the top of ceval.c
what kind of keywords are they talking about here?
just for/else/return etc?
lol it's been there since 1995
huh i see
HAVE_ARGUMENT¶
This is not really an opcode. It identifies the dividing line between opcodes which don’t use their argument and those that do (< HAVE_ARGUMENT and >= HAVE_ARGUMENT, respectively).
Changed in version 3.6: Now every instruction has an argument, but opcodes < HAVE_ARGUMENT ignore it. Before, only opcodes >= HAVE_ARGUMENT had an argument.
>>> dis.opmap['HAVE_ARGUMENT']
Traceback (most recent call last):
File "<pyshell#72>", line 1, in <module>
dis.opmap['HAVE_ARGUMENT']
KeyError: 'HAVE_ARGUMENT'
is this a bug?
No
It's not an "opcode"
It's a constant on the opcodes module
3.6 changed a lot of how bytecode was parsed changed
Pushes a new function object on the stack. From bottom to top, the consumed stack must consist of values if the argument carries a specified flag value
0x01 a tuple of default values for positional-only and positional-or-keyword parameters in positional order
0x02 a dictionary of keyword-only parameters’ default values
0x04 an annotation dictionary
0x08 a tuple containing cells for free variables, making a closure
the code associated with the function (at TOS1)
the qualified name of the function (at TOS)
how do these flags work? how are they set? are they passed along as part of the instruction's argument?
is it literally just if arg & 0x01 then second popped value will be tuple of default values, etc?
oh wait that doesnt make sense, since it'd mess up the value of argc
oh, or maybe it just takes that into account
let's see what ceval.c has to say
oh im just really confused, nevermind, it all makes sense now. ignore me 😅
@brazen geyser feel free to help out with bytepatches btw, it has horrible parsing so far
@grave rover https://github.com/martmists/BytePatches this right?
the project im working on atm is inteded to be a python vm in another language but if i come across anything that applies to your project as well ill give a shout
im thinking the if/elifs in parse_bytecode might be better off as lambdas at indexes in a list
I mean you're pretty much using bytecode :p
Hm
But not all of them work as lambdas
how do you mean
im fairly new to this lower level part of the language so youll have to excuse my ignorance
e.g. im not sure what a nodevisitor is 😛
im trying to get the output of a dis as a string and so im passing a StringIO as the file param
unfortunately though it seems like there aren't any newlines in the output?
what am i missing
def dis_string(code):
result = io.StringIO()
dis.dis(code, file=result)
return result.getvalue()
nevermind, it was my mistake with qt's text edit widget
I figured out a way to get the builtins, including e.g. __import__ after running globals().clear(), but it's definitely cheating.
__builtins__, nothing = __builtins__, globals().clear()
import this```
anyone know where to find the source for python37.dll? i found this https://github.com/python/cpython/blob/master/PC/python3dll.c but it's a bit bare
what are you trying to find?
just want to see what python37.dll looks like inside
how does type construction work when you don't override __new__, considering object.__new__ accepts no arguments?
like, I figured construction is basically like this: ```py
def ...(cls, *args, **kwargs): # pseudo code for type.call
obj = cls.new(*args, **kwargs)
if isinstance(obj, cls):
obj.init(*args, **kwargs)
return obj
but that doesn't work because it passes args/kwargs to `object.__new__`
it checks if __init__ is defined
it looks like the relevant line for my question is L3767 a few lines up but
why is it !=
oh wait
probably if you call super().__new__ in your own new
for super().__n
yeah
so it ignores the arguments if the class has its own init
but if the class has its own new, that is expected to handle the arguments itself and, if it calls object.__new__ at all, do so without arguments
checks out: ```py
class C:
... def init(self): pass
...
object.new(C, 1, 2)
<main.C object at 0x0000000002AD0DA0>```
Compiling bytecode is really trivial
I like the next thing in the thread; the -> arrow for callables
strongly against it either. What I would like to add here is that if we
will go with the replacement:
Callable[[X, Y], Z] becomes (X, Y) -> Z
then we should also go with
Union[X, Y] becomes X | Y
Tuple[X, Y] becomes (X, Y)
Optional[X] becomes X?
(Intersection[X, Y] when added becomes X & Y)
The current syntax (although really verbose) is consistent, so if we want
to improve it I would like to keep consistency.
Also if we are going forward with this, should we allow mixing old and new
syntax? Will the old syntax be deprecated after we introduce the new one?```
Alrighty I'm working on a project that has to do with image recognition. I've got a bunch of collecters cards that have set images on them. What I want to do is take a picture of a card or present 1 and indentify which set that card came from.
I'm writing it in python and am thinking of using open-cv and a haars cascade algorithm. The issue is that requires 100's of positive and negative images. I can get the negative but IDK how I could get so many positive for each set or even an individual set. Is there another auggestion anyone could reccomend with tensorflow or any other python application?
this is not a good place to ask for actual help with python
Folks, apologies if this is not the right channel. Inside a primary jupyter notebook, i'm trying to load other ipython notebooks one by one and run them and capture any pandas dataframes that get generated and write them out to disk. Is there any way to get a secondary ipython shell context within an ipython context (just to keep the variable namespaces seperate)?
This seemed to be "esoteric" python to me, so I thought I'd ask here.
Is it possible to suppress errors in a one liner? Or a lambda
I mean I could do a exec
one line is a no, two is a yes
something tells me you could probably force it to one line, but it would be really damn horrendous to look at lol
with contextlib.suppress(Exception): expression
nope ```py
with contextlib.suppress(Exception): raise BaseException
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BaseException```
well then suppress baseexception :D
yep, that works ```py
with import('contextlib').suppress(BaseException): raise BaseException
...
ofc it works
That doesn't work the way I want it to
Since in a one liner now everything else you type will be in that
Since semi colons
while id:r=input("Enter temperature and units: (e.g. 32 F)\n");id=1if r else 0;s=iter(r.split(" "));t=next(s,"");e="No temperature was entered;quitting."if t==""else 0;exec("try:t=float(t)\nexcept:t=0");e=e or("Invalid temperature."if hasattr(t,"__or__")else 0);u=next(s,"").lower();e=e or("No unit specified."if u==""else 0);z={"f":lambda x:(x-32)*5/9,"c":lambda x:x*9/5+32};c=z.get(u,lambda x:0)(t);e=e or("Invalid unit."if c is 0else 0);y="C"if u=="f"else"F";print(f"[ANS] {c} degrees {y}\n")if id and not e else 0;print(e+"\n")if all((id,e))else 0
One liner with instructions. I have expanded version and much shorter version (which uses 1 and 0 instead of true/false and a bunch of other things, and does not contain instructions for what to do)
@sick hound you might like this: https://www.youtube.com/watch?v=DsUxuz_Rt8g
Speaker: Chelsea Voss We'll describe the ideas and implementation behind Oneliner-izer, a ""compiler"" which can convert most Python 2 programs into one line...
it's a "tool" that can automatically convert programs into one-liners. she figures out all sorts of horrible tricks to make it work
sure 😃
well, it's an extra-level challenge to write a program to modify your programs.
in the video, she explains things like how to get try/except in a one-liner
I'll still watch it of course. Be nice.
ah, ok! 😃
>>> dis.cmp_op
('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD')
what is BAD?
probably used in place of an invalid operator or something
wouldnt that raise a syntax error during compilation?
/shrug
For the maybe keyword challenge does it have to be 100% random, or could the value just change to random.choice([True, False] 100 times a second or something like that
that's up to you. :D
Hey guys, I was wondering if it was possible to import and use a modual within something that looks like this
print(eval("lambda x: x*2")(eval("int(input(\"Enter a value:\\n\"))")))
its just an example
So basically I need to use the modual in the lambda function
and It needs to be in one line, should have started with that
sorry for the hassel
Actually, heres the whole code
print(eval("lambda x: \"Correct\" if random.randint(1, 10) == x else \"Incorrect\"")(eval("int(input(\"Enter a number:\\n\"))")))```
Is it possible to oneline?
Oh, forgot semicolans existed, wow. Well if anyone figure out any way to do it without semicolans let me know
print((lambda x,random=__import__('random'):'Correct' if random.randint(1,10) == x else 'Incorrect')(int(input('Enter a number:'))))``` @honest lotus
What do you mean move the import? I'm kinda new to esoteric stuff
hence all the evals
Gimme a min I'll show you
ok
print((lambda x:'Correct' if __import__('random').randint(1,10) == x else 'Incorrect')(int(input('Enter a number:'))))```
@honest lotus
Thats interesting, didn't know you could call a method of a module in the command where you import it
Esoteric python is full of wonders
Yeah lol
(lambda x:x(x,(lambda x:[[[0]*len(x[i])for i in range(len(x))],x])((lambda a:(lambda x,y:[[[[x[r].pop(c),x[r].insert(c,'*')]if y[0][r][c]else[x[r].pop(c),x[r].insert(c,y[1][r][c])]for c in range(1,a-1)]for r in range(1,a-1)],x][-1])([a*[0]for x in range(a)],(lambda x:[[[[[(lambda x,y:[y.append(x[1][r][c]),x[1][r].pop(c),x[1][r].insert(c,y[0]+1)])(x,[])if x[0][l][j]else 0for j in range(c-1,c+2)]for l in range(r-1,r+2)]for c in range(1,a-1)]for r in range(1,a-1)],x][-1])((lambda x:[[[[x[0][r].pop(c),x[0][r].insert(c,int.from_bytes(open('/dev/urandom','rb').read(1),'big')/10>20)]for c in range(1,a-1)]for r in range(1,a-1)],x][-1])([[a*[0]for x in range(a)]for x in range(2)]))))((lambda i:i if i>2and i<12else exit())(int(input('Board Size (max 9): '))+2)))))((lambda x,y,p=(lambda x:[print('\x1b[1;32m ',*range(1,len(x[0])-1),sep=' '),[[[print(f'\x1b[1;32m{r}\x1b[0m',end='') if c == 0 else [print(' ',end=''),print(['■','F'][x[0][r][c]], end='')if x[0][r][c]!=2else print(x[1][r][c],end='')]for c in range(len(x[0])-1)],print()]for r in range(1,len(x[0])-1)],x][-1]),i=(lambda f,i:[f[0][int(i.split(',')[0])].pop(int(i.split(',')[1])),f[0][int(i.split(',')[0])].insert(int(i.split(',')[1]),{'f':1,'c':2}[i.split(',')[2].lower()]),[print('You Lose'),exit()]if f[1][int(i.split(',')[0])][int(i.split(',')[1])]=='*'and i.split(',')[2].lower()=='c'else f][-1]),q=[]:[p(y),q.append(i(y,input('Type Row,Column,[(F)lag or (C)lear]: '))),x(x,q[0])if not (lambda y,q=[],w=[]:[[[q.append(y[0][r][c]==1and'*'==y[1][r][c])for c in range(len(y[0][r]))]for r in range(len(y[0]))],q][-1].count(1)==[[[w.append(y[1][r][c]=='*')for c in range(len(y[1][r]))]for r in range(len(y[1]))],w][-1].count(1))(y)else print('You Flagged All The Bombs!')]))``` This is one line minesweeper i did a while ago. input is (Row),(Column),(F for flag or C for clear) ex: 1,1,C @honest lotus
itll look weird if you run it on windows tho
actually it won't work on windows
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <listcomp>
File "<stdin>", line 1, in <listcomp>
FileNotFoundError: [Errno 2] No such file or directory: '/dev/urandom'```
Is there a way to assign variables in lambdas without causing a syntax error?
maybe locals()?
If you need to assign variables, you should probably just use a regular function instead
Oh I just scrolled up and saw the lambda XD
Also, is there a way to change the value of an argument of a lambda without raising an error?
example?
eg: lambda x: x += 1 without raising an error
one sec
testing something
lambda x: locals().update({'x':x+1})
@gilded orchid
oh wow, thanks
np
hmm
wait
@gilded orchid lambda seems to ignore .update on its locals
it doesnt error, but wont work
ah nvm then
however there is a hacky way of doing it
lambda i,x=[0]:[x.pop(),x.append(i),x[0]][2] returns i
but you could do lambda i,x=[0]:[x.pop(),x.append(i+1),x[0]][2]
which would return i+1
and you could use x later in the program
also, if you have lists as defaults in a lambda, you have some fun properties
x = lambda i=None,x=[]:x.append(i) if i else x
x(9) #returns nothing
x() #returns [9]
x(10) #returns nothing
x() #returns [9,10]``` @gilded orchid
btw that works with any mutable variable as a default
so dict works too
newCard = type(
'Card', (object,),{
'__init__':lambda self,card,suit:[
setattr(self,'card',card),
setattr(self,'suit',suit),
setattr(self,'visible',False),
None
][3],
'setVisible':lambda self,o=1:setattr(self,'visible',o),
'getSuit':lambda self,c=0:[f'\x1b[1;{31 if self.suit <= 1 else 0}m' if c else ''][0] + '♥♦♣♠'[self.suit] + ['\x1b[0m' if c else ''][0],
'fullCard':lambda self,f=0:self.getSuit(self.visible or f)+self.card if self.visible or f else '[]',
'getValue':lambda self:'A23456789XJQK'.index(self.card),
'getColor':lambda self:'red' if self.suit <= 1 else 'white'
}
)``` in case you ever want to make a class without ``class`` keyword (can also be condensed to one line)
This is a collection of some Python lambda oneliners I made some time ago: https://github.com/Defelo/python-oneliners
@rugged sparrow that stuff with mutable default args in a lambda applies to regular functions too.
@rugged sparrow could you explain why there is a [3] on the init and a [0] on the getsuit?
@brisk zenith didn't know that, but it makes sense when I think about it
@honest lotus there is a [3] on __init__ because __init__ has to return None
There is a [0] on getSuit because I used list comprehension to separate operations, and that gets the value out of the list
@rugged sparrow is there like a guide or something for that?
Seems pretty interesting
(lambda _,__,___,____:getattr(getattr(__import__(True.__class__.__doc__[(_*____*_)]+True.__doc__[(___*_)**_+__*___]+True.__class__.__doc__[____*(True+__)]),__import__(True.__doc__[True-___]+True.__class__.__doc__[(___*_**_+__)*___]+True.__doc__[(_+__)*____+True]).__doc__[int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___))):int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___)))+_*__]),getattr(__import__(chr((___*_)**_+__*___)+True.__doc__[(___*_**_+__)*___]+True.__class__.__doc__[True-___]),__import__(chr((___*_**_+__)*___)+True.__class__.__doc__[(___*_)**_+__*___]+True.__doc__[(_+__)*____+True]).__doc__[int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___))):int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___)))+_*__]).__doc__[int(True.__int__().__str__()+str(True*__)+False.__int__().__str__()+str(__*__)):int(True.__int__().__str__()+str(True*__)+False.__int__().__str__()+str(__*__))+___]+getattr(__import__(chr((___*_)**_+__*___)+True.__doc__[int(True.__int__().__str__()+True.__int__().__str__()+str(___))]+chr((___*_)**_+__*___)),__import__(chr(int(True.__int__().__str__()+True.__int__().__str__()+str(___)))+True.__doc__[int(True.__int__().__str__()+True.__int__().__str__()+str(___))]+True.__class__.__doc__[____*(___-True)]).__doc__[int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___))):int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___)))+_*__]).__doc__[((__*__-__**__)+_*_)*____:(__*__-__**__)*____]+True.__class__.__doc__[____*_**_])(True.__doc__[_**___-True].upper()+True.__class__.__doc__[__**__-__*__]+True.__class__.__doc__[__]*_+True.__doc__[True]+True.__class__.__doc__[_^___]+chr((_**___+_**_*_)*_+___^_)+chr(___*___*_**_+_*___+True)+chr((_*(___*_)*___)+_**_+___*_)+True.__doc__[__]+chr((___*_)**_)+True.__class__.__doc__[__*___]))(True<<True,(True<<True)+True,(True<<True<<True)+True,True.__class__.__doc__.find(chr(False)))```
@gilded orchid i made my own (it was an obfuscated hello world
@brisk zenith i saw that obfuscated hello world in the pins and decided to make my own
I noticed a lot of the one liners have nested lambdas within [] and make use of and and or. Would someone mind explaining it a bit?
and and or can be used as conditionals instead of if because of something called short circuiting. Basically, if you check False and some_func(), then Python will get to the False then realise that the other argument doesn't matter because there's no way for the statement to return True, so it doesn't bother to call the function on the right. So if the left value is falsy it returns that value. Note that it doesn't always return False, it just copies the left value. The left value could be 0, and empty string or list, None, etc. Python already knows it's falsy. If the left value is truthy, it returns the right value instead, whatever it may be, because Python knows the right value in that case has the same value as the whole and clause. So, in effect, a and b is a if not a else b. A similar thing happens for or
What about lambdas within other lambdas using []
Would (True) be considered true-ey? @snow beacon
Oh, sorry, did I say it wasn't?
True is truthy, false is falsy.
Most objects are truthy, exceptions being None, False, 0, empty sequences, empty dicts, empty sets, and probably a bunch of other things I'm forgetting.
yeah that pretty much covers it
excluding things that override __bool__ like Decimal and range
mostly, anything that's 0y or emptyy is falsey, and anything else is truthy
Here;s a challenge guys
A python oneliner that says "hello world" but looks like the word "Hello" in markdown
@fast torrent example?
I have no idea if its possible
ah
@fast torrent ['Hello World'](print(f'Hello{chr(32)}World')) this will do it
but will throw an error after printing Hello World
@fast torrent ```py
p = print ; s =' ';
h = 'h ' ; r =
'rep' 'lac' ; r = r\
- r [ 1 ] ; (
) ; eval( 'p('+ '"hell o".'
\ - r +('(" " , "")+'
) + ' " " [ 0
]+"wo rld". ' + r +
' ( " " [ 0 ]
, " "*0))');1+1 +1+1+ 1+1+1
that's really fun actually
there aren't enough consecutive non-spaces for "replace" or "getattr" so I put the whole thing in an eval
there's a bit of unnecessary code at the end and that sort of thing but that's all cool, it does the job.
[' ', print( '', 'H' +'ello'
, '' ,'' '', '' , ''
),111, print( '', 'W' + 'o'
+ '' + ''+ '' + ''
+ '' +'rld' ,'' ,'' ,'' ),]```
this works
@fast torrent
Cool.
challenge 07 is upon us: code art!
we're changing things up today (as always, really). your submission may do whatever you want it to, but it must do something and follow the theme of code art, like the messages(s) just above this one :D
i hope we get some really unique submissions this time around, it's very open-ended. more details and examples can be found on the repository here: https://github.com/python-discord/esoteric-python-challenges/tree/master/challenges/07-code-art
i'm always nervous about getting something wrong when doing that :D i don't think i did this time though.. 👀
wat
i'm still confused.
@brisk zenith I mentioned the code art idea a few days ago
Then you made challenge 7
oh, i see. i had the idea in my head quite a while ago but didn't know how well it'd work until you mentioned it.
@spice wing check out this challange
print(['No ' +'One' ,'X','O' ][( lambda x=\
( lambda f:[f( ) for _ in range(9)]
)( lambda b=[* range (9) ],u= [' ']\
*9,f=[0,1]: [(lambda p:[p(u), p(b) ])( lambda\
a,p= print\
:[p('_'*7),[p('\x1b[4m',*a[x:x+3],'\x1b[0m',sep='|')for \
x in[ 0,3,6\
]]]), (lambda i: [ u.pop(i),
u.insert( i,'XO' [f[1] -1])
])(( lambda c=[0]: [c.pop\
(),[_ for _ in iter(lambda:\
(lambda i=input(\
'XO'[f[1]-1]+': '):0if[any([0if x in map(chr,range(48,58))else\
1for x in i]\
)if len (i)else 1][0]else [c.append (int(i)),
1][1]if int(i)>=0 and int (i)<=8 and' '\
==u[ int(i)] else 0 )(),1)],c[0]]\
[2]) ()),( lambda: [f.pop (0),\
[], [], f.insert( 0,f[0])] if 1in [all(
[u[ int(x) ]=='XO' [f[1]-1] for x in str([\
\
*map(ord,'ÒřʦɶơĂ͈ö') ][y])])\
for y in range(8)] else 0)(),
f.append( [0,2,1]\
[f.pop(1) ])]if 0\
==f[0] else f[ 0]):0if x\
[-1]not in[1,2]else x[-1])()],'Wins')```
@brisk zenith would this be a valid submission to the newest challenge?
@cold mirage its tictactoe
im not questioning what it is, im questioning your sanity
oh then definitely
I question his sanity 24/7... he refuses help
@brisk zenith can I resubmit my heart code but in the shape of the word "heart"
@grave rover of course you can :D
but don't forget, words aren't the only form of art. it would be nice to get some other creative submissions too ^~^
resubmits heart code
haha, the main idea of this challenge is to be unique and interesting
@brisk zenith did my submission go thru?
i mean, it certainly can if you want me to merge. it does look a little wonky though! haha :D
i think you've got a really good idea though
tic tac toe written in code that looks like tic tac toe. pretty neat for sure.
i think it would look really cool if you managed to make the grid line up properly and all that. it's perfectly fine if you can't manage that, but it's nice to make it a little more challenging for people who enter submissions so quickly :D
lol sounds good
print(['No ' + 'One' ,'X','O' ] [ ( lambda x=
( lambda f:[ f( ) for _ in range(9)]
)( lambda b = [* range (9) ], u= [' ']\
*9,f=[0,1]: [(lambda p:[p(u), p (b) ])( lambda
a, p= print
:[p('_' * 7),[p('\x1b[4m',*a[x: x + 3] ,'\x1b[0m', sep='|')for
x in [ 0,3, 6
] ] ]),( lambda i:[u.pop(i),
u.insert (i,'XO' [f[1] -1])
] ) ( ( lambda c=[0]: [c.pop(
),[_ for _ in iter(lambda:(
lambda i =input(
'XO'[f[1]-1]+': '):0if[any([0if x in map(chr,range(48,58))else
1 for x in i]
)if len(i )else 1] [0]else [c.append (int(i)),
1][1]if int(i)>=0 and int (i)<=8 and' '
== u[ int(i) ] else 0) (),1)],c[0]]
[2] )() ), ( lambda: [f.pop (0 ),
['/' ],f .insert( 0,f[0]) ]if 1 in[all(
[u[ int( x)]=='XO' [f[1]-1 ]for x in str([
*map(ord,'ÒřʦɶơĂ͈ö') ][y])])for y in range(8)] else 0)
(),f. append ([0,
2,1][ f.pop( 1)])
]if 0 ==f[0] else
f[0]) :0if x [-1]not in[1,2]else
x[-1])()],'Wins')```
@brisk zenith i straightened it up a bunch, and made the stuff at the bottom something other than a random blob lmao
i think i might change that last row and make the last x a bit smaller tho
looks quite a lot better, actually! feel free to make any new commits to your PR and let me know when you think you've done the best you can so i can merge it in.
Sounds good, will do
Prints a spiral and looks like a spiral!
@brisk zenith its done now
oh neat, looks great! thanks for submitting your code, i'll merge it now
thanks
@keen moth that's really cool, and it's shaped so perfectly too. good job! is it ready for merging?
okay! thanks for participating :D
oh and of course, i think i'll allow people to give multiple submissions for a challenge if they so wish. i don't see why not ^~^
d37d128 Create chilaxan.py - chilaxan
09331f8 Update chilaxan.py - chilaxan
2cd0f1a improve chilaxan.py - chilaxan
f39b69a Merge pull request #15 from chilaxan/patch-1 - kingdom5500
print(__import__('random').choice(
[( '1'
)+ chr(int(ord('ǂ')/ 10
)) +chr( 5*17 )
+ chr(2 *56) ,
'' +chr( 7*11 )
+ chr( 5*23 +2
)+ chr(5* 23
)+ chr(10* 10
+4 )+chr( 5*
22 +2*2)+ ''
+ chr(2* 56
-1 )+chr( 37
* 3
)+ chr(99 +
10 ),chr( 83
)+ ''
+chr(4*29)+chr(4*24+1)+chr(114)]))
Finally finished this mario question mark block, that outputs 'Star', 'Mushroom' or '1-Up'
How do I submit it to the github solutions thing? (I haven't used github before)
it's covered pretty clearly in the repository readme: https://github.com/python-discord/esoteric-python-challenges/#adding-your-solution-to-the-repository
but if you still need a hand with it, i can help you :)
looks like a wonderful solution, by the way.
I had a fun idea but I doubt it's doable
Does anyone here know Tupper's self-referential formula?
yes it can, and there's a numberphile video on it: https://www.youtube.com/watch?v=_s5RFgd59ao
Matt Parker discusses Tupper's Self-Referential Formula. More links & stuff in full description below ↓↓↓ Matt's book on Amazon (US): http://bit.ly/Matt_4D_U...
@grave rover what's you idea for it?
Write code in that shape that outputs that shape
That formula is kinda "cheaty" since it uses a constant which is what actually affects what the output looks like
So you could write code that works on the same principle
https://cdn.discordapp.com/attachments/470884583684964352/574028065873723403/DVMnaKkUMAAfLQ0.jpeg
in that image, k is (i think) 960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719
hoping I did that right
@gilded orchid yup, looks good. that's a really cool submission, i'll merge it when i get on my computer at some point later today :D
ok, thanks 😃
(lambda x: (print('1'),print('2')))(1) Is there a way to stop this from printing (None, None)?
try not running it in a python REPL
not exactly
you can't use an actual while loop because that's a statement
but you can use py [whatever for _ in iter(lambda: condition, True)]
If you changed that True to False would it function like while not:?
yes
oh ok, makes sense
except the condition has to evaluate to either True or False
[whatever for _ in iter(lambda: bool(condition), True)]``` would be more accurate
wow, my next thing for the code art challenge is bigger then my screen at the moment
I've had to lower the font size
also, could 'whatever' be a list/tuple of code? @sick hound
ok, thanks for the help
that formula is amazing
how do you even come up with something like that
dark sorcery
oh wait
@gilded orchid i got that the wrong way round
it should be iter(lambda: bool(condition), False)
@gilded orchid what are you doing?
Trying to make a simulator for a Pokemon battle, that spells out the word Pokemon
for the code art challenge
That's amazing
@gilded orchid if it would make it easier, you can make legit classes (with self) in one line using type()
yup, type(class_name, bases, attributes).
example: ```py
class Dog(Animal):
Dog = type("Dog", (Animal,), {
# set a class-level attribute like this:
"BASIC_COLOURS": ["black", "brown", "white"],
# def __init__(self, colour):
# self._colour = colour
#
"__init__": lambda self, colour: setattr(self, "_colour", colour),
# @staticmethod
# def make_sound():
# print("woof")
#
"make_sound": staticmethod(lambda: print("woof")),
# @classmethod
# def new_random(cls):
# return cls(random.choice(cls.BASIC_COLOURS))
#
"new_random": classmethod(
lambda cls: cls(random.choice(cls.BASIC_COLOURS))
),
# @property
# def colour(self):
# return self._colour
#
"colour": property(lambda self: self._colour)
})
i actually think that's a really nice demonstration of manual type initialisation
and of course, with comments and newlines removed, you get this: ```py
Dog = type("Dog", (Animal,), {"BASIC_COLOURS": ["black", "brown", "white"], "init": lambda self, colour: setattr(self, "_colour", colour), "make_sound": staticmethod(lambda: print("woof")), "new_random": classmethod(lambda cls: cls(random.choice(cls.BASIC_COLOURS))), "colour": property(lambda self: self._colour)})
it looks like chaos but it really does make a lot of sense if you just break it down and comment it properly as i've shown.
that is a very nice example of using type()
allows you to have fully object-oriented programs in one line. perfect for #esoteric-python.
in fact, for one of the first challenges submitted here (polish notation evaluator) i built a full stack class manually in one line because lists were prohibited. i believe basically anything is possible in one line if you break it down enough
oh definitely
globals.update({'Dog':type('Dog', (Animal,), {...})})``` you can even add it to globals in one line
yup
@brisk zenith did you ever figure out how to do oneline'd try,except?
nope, but i'd be lying if i said i tried :D
been quite busy recently so it's not a priority for me at the moment
@brisk zenith py try_except = lambda t,e,x=Exception:[exec('def q(t,e,x):\n\ttry:return t()\n\texcept x as p:return e(p)'),eval('q(t,e,x)')][1] ik this is cheating, but it does work
¯_(ツ)_/¯
try_except = lambda t,e,x=Exception:[(lambda:0).__class__(compile('def q(t,e,x):\n\ttry:return t()\n\texcept x as p:return e(p)','','exec'),globals())(),q(t,e,x)][1]``` doesnt use exec() or eval() now
technically
I was thinking of manually using contextlib.suppress
however it only works in with statements
I did do the same thing as above when I had to
there has to be some way to do it
smart
from what juanita was doing with classes, you can copy code from https://github.com/python/cpython/blob/3.7/Lib/collections/__init__.py#L910-L916 to get a keyerror handler
slightly dodgy lol
https://github.com/python/cpython/blob/3.7/Lib/concurrent/futures/_base.py#L321-L326 here's a way to call arbitrary functions and hide the error
https://github.com/python/cpython/blob/3.7/Lib/concurrent/futures/process.py#L194-L201 wait I think this might work
arbitrary function that handles errors
thats perfect
you just need some boilerplate
also thats only in cpython
what's wrong with that
If I'm searching through stdlib it's probably only gonna be cpython
wait actually that won't even work
the thing I found
actually
uhh
sorta
you'd have to create a queue objet which the put method does the actual function
ie. it can raise an error
darn it I was looking at contextlib before
dang
lol
doesn't do python 3 tho
compile('def q(t,e,x):\n\ttry:return t()\n\texcept x as p:return e(p)','','exec')```
"doesnt use exec"
mfw
@tepid beacon i said technically
if anything it uses is technically
PEP0463 😦
Are there any code editors that help when making one liner stuff? E.g: a pretty view option
I'm getting kind of annoyed using Idle
Can you go into more detail? What is it you're looking for from an editor regarding one liners?
@sick hound i solved it
tryExcept = type('tryExcept',(__import__('contextlib').ContextDecorator,),{
"__init__":lambda self,f=lambda:None,e=Exception:[setattr(self,'e',e),setattr(self,'f',f)][0],
"__enter__":lambda self:None,
"__exit__":lambda self, *args:[[True,self.f()][0] if self.e in args[0].__mro__ else False][0] if args[0] != None else False
})```
tryExcept()(lambda:1/0)() ^ no crash
tryExcept(e=KeyError)(lambda:1/0)() ^ crash, cause we are checking for KeyError
tryExcept(f=lambda:print('i tried to divide by zero'),e=ZeroDivisionError)(lambda:1/0)()
^ runs f, as a ZeroDivisionError was called
@brisk zenith ^^
lambda's don't do kwargs
yes they do
what
also obv the second would crash
well yes demonstrating the difference between kwarg and arg
what version of python?
yea i thought it made more sense
@sick hound i should prob sleep now
its 2 am here
🙃
ha
@rugged sparrow ```py
from contextlib import suppress, ContextDecorator
suppress = type("suppress", (suppress, ContextDecorator), {})
suppress(ZeroDivisionError)(lambda: 0/0)()
there we go
using contextlib.suppress
doesn't have the default Exception but it does support mutltiple exceptions
@sick hound but can it do except
good point it can't
dont get me wrong, my implementation can def be improved, and probably isnt the best way to do it
also you have lots of [statement][0] for no reason
thats to make sure stuff happens in the right order
also __init__ has to return None
but just use (statement)
well now its 3 am
really?
last i checked it was enforced
>>> class d():
... def __init__(self):
... return 1
...
>>> d()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'int'
>>>
``` @sick hound
lol
same here
espescially when im substituting caffine for sleep
also spelling left
are you agianst semicolons
yup
and semicolons are against that spirit
for your finally, just add it to exit
but remember that __exit__ has to return True
if you want the exception to be ignored
ah yes, i've considered using contextlib for it but i wanted to see if i could get it to work with no imports :D still, subclassing it is definitely something i didn't think of, so it's a nice solution anyways.
type(exit).__call__.__globals__['sys'].modules['contextlib']```
@brisk zenith technically no imports :P
interesting
I don't think people really know what technically means
Because technically it has had to have imported it in the first place
but doesn't sys.modules['contextlib'] need contextlib to have been imported elsewhere first?
yes, it does
but contextlib has already been imported somewhere when the interpreter starts
C:\>python
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> type(exit).__call__.__globals__['sys'].modules['contextlib']
<module 'contextlib' from 'C:\\Users\\Aaay\\AppData\\Local\\Programs\\Python\\Python36\\lib\\contextlib.py'>
>>>```
C:\>python
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> type(exit).__call__.__globals__['sys'].modules.keys()
dict_keys(['builtins', 'sys', '_frozen_importlib', '_imp', '_warnings', '_thread', '_weakref', '_frozen_importlib_external', '_io', 'marshal', 'nt', 'winreg', 'zipimport', 'encodings', 'codecs', '_codecs', 'encodings.aliases', 'encodings.utf_8', '_signal', '__main__', 'encodings.latin_1', 'io', 'abc', '_weakrefset', 'site', 'os', 'errno', 'stat', '_stat', 'ntpath', 'genericpath', 'os.path', '_collections_abc', '_sitebuiltins', 'sysconfig', '_bootlocale', '_locale', 'encodings.cp1252', 'types', 'functools', '_functools', 'collections', 'operator', '_operator', 'keyword', 'heapq', '_heapq', 'itertools', 'reprlib', '_collections', 'weakref', 'collections.abc', 'importlib', 'importlib._bootstrap', 'importlib._bootstrap_external', 'warnings', 'importlib.util', 'importlib.abc', 'importlib.machinery', 'contextlib', 'mpl_toolkits', 'atexit'])
>>>``` all of those modules have already been imported by something
@brisk zenith
(i included the cmd command and startup message to show that I haven't done anything else)
well yeah i know that. let me rephrase then, "without stdlib modules used".
or other modules
stop being pedantic.
Yeah I'm not sure how you would do try/except without stdlib
it's an interesting challenge
*or exec/eval (technically this is not one liner as it has \n)
(...are we allowed non-stdlib modules? :P)
i don't think there's any way to do that
unless you allow codetype/functiontype
well there is
http://onelinerizer.com has a solution
it uses contextlib
seriously?
(lambda __contextlib, __print: (lambda __out: (lambda __ctx: [__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: __exctype is not None and (issubclass(__exctype, Exception) and [True for __out[0] in [((__print('b'), lambda after: after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: [False for __out[0] in [((__print('a'), (lambda __after: __after()))[1])]][0]})())))([None]))(__import__('contextlib', level=0), __import__('__builtin__', level=0).__dict__['print'])```
yes
oh yeah
Just read source rather than checking try/except \🤦
type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\nd\x00\x83\x00\x01\x00W\x00n*\x04\x00e\x00k\nr4\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda:1/0,lambda e:print(e),None),('BaseException','e'),(),'','',0,b''),globals())()```
@brisk zenith @sick hound is that cheating?...
does it use try/except... by evaluating
and it uses \n so no
what
why are you not allowing \n
it doesn't make any sense to disallow it there
because it's a newline?
If you're allowed to craete text newliens you can just eval it
All you're dooing it making it more abstract evals
type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:1/0,lambda e:print(e),None),('BaseException','e'),(),'','',0,b''),globals())()```
@sick hound there, there aren't any newlines anymore. happy?!
@sick hound cant get return value, and can it do except?
it can do except, but it catches all exceptions and you have to decide yourself which exceptions you want and rethrow the ones you don't
ah
(lambda f,e,l=[]:(type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:l.append(f()),lambda x:l.append(e(x)),None),('BaseException','e'),(),'','',0,b''),globals())(),l.pop())[1])```
now it can get the return value
nice
@sick hound is that just the bytecode for try except?
yes
ah
>>> import dis
>>> dis.dis(type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:l.append(f()),lambda x:l.append(e(x)),None),('BaseException','e'),(),'','',0,b''),globals()))
0 0 SETUP_EXCEPT 12 (to 14)
2 LOAD_CONST 0 (<function <lambda> at 0x000001FEE2FA1E18>)
4 LOAD_CONST 0 (<function <lambda> at 0x000001FEE2FA1E18>)
6 CALL_FUNCTION 1
8 POP_TOP
10 POP_BLOCK
12 JUMP_FORWARD 42 (to 56)
>> 14 DUP_TOP
16 LOAD_NAME 0 (BaseException)
18 COMPARE_OP 10 (exception match)
20 POP_JUMP_IF_FALSE 54
22 POP_TOP
24 STORE_NAME 1 (e)
26 POP_TOP
28 SETUP_FINALLY 14 (to 44)
30 LOAD_CONST 1 (<function <lambda> at 0x000001FEE4F75510>)
32 LOAD_NAME 1 (e)
34 CALL_FUNCTION 1
36 POP_TOP
38 POP_BLOCK
40 POP_EXCEPT
42 LOAD_CONST 2 (None)
>> 44 LOAD_CONST 2 (None)
46 STORE_NAME 1 (e)
48 DELETE_NAME 1 (e)
50 END_FINALLY
52 JUMP_FORWARD 2 (to 56)
>> 54 END_FINALLY
>> 56 LOAD_CONST 2 (None)
58 RETURN_VALUE```
im trying to figure out a way to do mine without imports
tryExcept = type('tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
"__init__":lambda self,f=lambda:None,e=Exception:[setattr(self,'e',e),setattr(self,'f',f)][0],
"__enter__":lambda self:None,
"__exit__":lambda self, *args:([True,self.f()][0] if self.e in args[0].__mro__ else False) if args[0] != None else False
})
``` @brisk zenith would you count this as no imports?
i suppose so :D
@brisk zenith is this no imports? py (lambda f,e,l=[]:(type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:l.append(f()),lambda x:l.append(e(x)),None),('BaseException','e'),(),'','',0,b''),globals())(),l.pop())[1])
tryExcept = type('tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
"__init__":lambda self,f=lambda:None,e=Exception:[setattr(self,'f',f),setattr(self,'e',e if isinstance(e,list) else [e])][0],
"__enter__":lambda self:None,
"__exit__":lambda self, *args:[True,self.f()] if args[0] != None and any([e in args[0].__mro__ for e in self.e]) else False
})``` neaten'd up a bit, also can now take a list of exception types
tryExcept = type('tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
"__init__":lambda self,f=lambda:None,e=Exception,p=False:[setattr(self,'f',f),setattr(self,'e',e if isinstance(e,list) else [e]),setattr(self,'p',p)][0],
"__enter__":lambda self:None,
"__exit__":lambda self, *args:[True,self.f(args[1]) if self.p else self.f()] if args[0] != None and any([e in args[0].__mro__ for e in self.e]) else False
})``` and now it has the optional flag ``p`` which will make it give the exception instance to the ``except`` lambda (``f``)
Could there be a folder on the GitHub just for silly workarounds that people find for the limitations of lambdas?
E.g: that try/except thing, the while loop thing from a while ago and defining globals
@gilded orchid you mean while loop with iter()?
yeah
i think we should have that
e.update({'h':b[int(input(''+f'1:{b[5][0]} '+f'2:{b[6][0]}'+' '+f' 3:{b[7][0]}) 4:{b[8][0]}'))+4]})
I keep on getting errors that I'm giving update 2 arguments instead of just one (e is globals() and b is a tuple)
(also this is part of my code art thing which is why it looks so weird)
(also that input thing is pretty much just 1 2 3 or 4)
@sick hound i guess so, but i feel like that's some sort of cheating. you're just doing eval but with bytecode, more or less. still, that's an interesting way of doing it for sure :D
@gilded orchid idk why that would say your giving it 2 args
but do you want my input handler that i wrote for my tictactoe?
nvm, turns out I missed out a comma earlier and it took me 10 minuites to work that out
it makes sure input is a number in a range
I think it's fine as it is, I'm kind of running out of space to finish this off so I don't really want to add anything else in the earlier bits of my code
ah makes sense
@brisk zenith what do you think about making a github repo for workarounds like this?
(1.5 if h[1] in b[1:3] else 1)
Is there a way I could get this to work with a new line between [1:3] and else?
nvm turns out I can put the newline before the last square bracket for it to work
tryExceptRet = lambda t,args=[None],f=lambda e=0:None, e=Exception,r=[],y=[]:[
y.clear(),
y.append(type(
'tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
"__init__":lambda self,f=lambda:None,e=Exception,p=False:[setattr(self,'f',f),setattr(self,'e',e if isinstance(e,list) else [e]),setattr(self,'p',p)][0],
"__enter__":lambda self:None,
"__exit__":lambda self, *args:[True,r.append(self.f(args[1])) if self.p else r.append(self.f())] if args[0] != None and any([e in args[0].__mro__ for e in self.e]) else False
}
)
),
r.clear(),
r.append(y[0](f=f,e=e,p=f.__code__.co_argcount == 1)(t)(*args) if t.__code__.co_argcount else y[0](f=f,e=e,p=f.__code__.co_argcount == 1)(t)()),
r[0]
][4]``` now the return value is either try or except lambda respectivly, and its one call that looks like ```py
tryExceptRet(t=lambda a:a/0,args=[1],f=lambda: 'error',e=ZeroDivisionError)```
args is passed to try lambda with *args
tryExceptRet(t=lambda a:a/0,args=[1],f=lambda err: f'error:{err}',e=ZeroDivisionError)``` and all you have to do to get exception passed to except lambda is make it have one arg
globals().update({'a':1, 'b': a+1}) Is there a way to get something like this to work without using a second update?
It gives an error saying that a is not defined
That's just an example of it since posting my actual code would be a nightmare
nvm then