#esoteric-python

1 messages ยท Page 77 of 1

nocturne saddle
#

Oh, boy, the introduction of bool in Python 2.3 was drama

#

I guess the walrus shows nothing has really changed there

edgy kelp
#

huh didn't know that, what was the drama around it?

marsh void
#

well, no drama but discussions were tough as far as I have read from PEP 285

lament ibex
#

didn't even know Python used to not have booleans

marsh void
#

we didn't even have str() as it is in python 3, in python 2

#

wait it really is blocked for me

sick hound
#

Wait about overriding tuple comparisons?

#

Make then always return true

#

Or at least return true if the arguments are (true, false) and (false, true) @marsh void

next mist
#

hey this code is pretty good right? the programming discord didnt like it

from subprocess import *

global USEr_INPUt
USEr_INPUt = input("enter stuff here:" )

def DOthingsHERE():
  for X in range(1,5):
    for v_V in range(1,5):
      for bIrDs in range(1,6):
                R = X
                hELLO = v_V
                BiRdS = bIrDs
                print (str(BiRdS)+str(int(str(hELLO)))+str(R))
                
DOthingsHERE()
subprocess.call([USEr_INPUt], shell = True)```
sullen rock
#

So it looks like there are maybe patterns in you capitalization - you'll wanna try to limit that as much as possible. Maybe try a language like PowerShell where you can capitalize variables differently each time.

#

Other than that, it looks solid and in no way incredibly dangerous.

next mist
#

so i need less patterns, gets too predictable

#

predictable code == bad code

#

easy for hackers to break

lament ibex
#

Suggestions: script isn't accessible via the web, what happens if I want to access it on the go. Also you should automatically append 'sudo' to the subprocess arg list, I hate having to retype commands.

next mist
#

Well this is a windows environment, but I could have our Networks root password stored and prints so they don't forget it

#

And on the front of making it not accessible on the go, I can open up ports so you could use psexec to run it remotely

snow beacon
#

Maybe give it a captcha, so hackers don't use it.

next mist
#

That's crazy, I'll just put a input that doesn't let you continue unless you type that you won't be bad

sullen rock
#

sys.stdin = io.StringIO(r0oTpAs$w0rD) might do it

next mist
#
Test = input(" are you bad? >>>")
If test != "":
 Continue()
Else:
    Continue()```
I think that would work without being too strict
sullen rock
#

Please publish this on pypi as REEEEEEEcaptcha

next mist
#

I'm worried about security though if I put it out to the masses wouldn't that be a vulnerability

sullen rock
#

I think you just have to dispute any CVEs people file for and you'll be okay

next mist
#

Oh okay in all reality they user input check of are you bad should really catch any bad doers

sullen rock
#

we should write a white paper this is brilliant

next mist
#

I Don't know that can cover the complexity of this though

#

Maybe make a catchy tik tok series on it, easier to remember and fun to learn

next mist
#

I don't want to have to dispute CVEs though, so I'll import random and use randomint(10000,100000000) to generate all my variable names

#

More secure

#

The less words the better

#

Code == secure
Passwords == secure
Secure == more character and no words.
So my code needs more characters generated randomly and no words when possible

snow beacon
#

Sounds like Pyth

gilded orchid
#

yeah I agree

#

pyth has a load of predefined variables that don't really make any sense

sullen rock
#

I feel like that's almost as far as I can go with confusing string formatting, but I'm really wondering if there's a good way to bury the easter egg's existence even deeper somehow

#

The main reason I published this code in the first place is because the idea of getting this into other people's programs delights me

sick hound
#

@next mist just hash variable names if ur going through all of that

brazen geyser
#

is there an easy way to only allow instantiation of a class inside one of its classmethods?
and in a way that is done transparently unlike https://stackoverflow.com/a/42735965 where the classmethod has to be defined inside the metaclass' __new__

sick hound
#

What's wrong with raising an exception in __init__

brazen geyser
#

then you cant instantiate it anywhere

sick hound
#

Isn't this the whole point?

#

Just use __new__ in the class methods

brazen geyser
#

the point is youd be able to define everything as usual i.e.

class SomeClass:
    def __init__(self):
        self.thing = 0
        self.other_thing = 0
    
    @classmethod
    def from_int(cls, value: int):
        result = cls()
        result.thing = value
        return result        

    @classmethod
    def from_float(cls, value: float):
        result = cls()
        result.other_thing = value
        return result
#

then just drop in a metaclass or a decorator or something and prevent new_object = SomeClass() outside of the classmethods.

#

im working on an approach rn thatll step through the stack and check each caller but it's a bit difficult

brazen geyser
#

almost done. now just need a reliable way to check whether a method is a classmethod.

#
import inspect
from functools import wraps


def callers():
    for frame_info in inspect.stack()[2:]:  # type: inspect.FrameInfo
        frame = frame_info.frame
        name = frame_info.function

        yield name, frame.f_code


def no_init(cls: type):
    old_init = getattr(
        cls, '__init__',
        lambda self, *args, **kwargs: None
    )

    @wraps(old_init)
    def new_init(self, *args, **kwargs):
        for name, code in callers():
            try:
                method: callable = getattr(cls, name)
            except AttributeError:
                pass
            else:
                if method.__code__ == code:
                    if (
                        inspect.ismethod(method) and
                        method.__self__ is cls
                    ):
                        break
        else:
            raise RuntimeError(
                'Instantiate this class using one of the classmethods.'
            )

        old_init(self, *args, **kwargs)

    setattr(cls, '__init__', new_init)

    return cls


@no_init
class Test:
    def __init__(self):
        print('ayy')

    @classmethod
    def from_int(cls):
        return cls()

Test.from_int()
Test()

done

#

i spent too long trying to figure out how to get the function object directly, then realised you could just compare the __code__

#

actually that should be method.__code__ is code probably, just to be extra sure

#

the traceback isn't very good though

#
Traceback (most recent call last):
  File "C:/Users/admin/Documents/Projects/shared_memory/scrap.py", line 137, in <module>
    Test()
  File "C:/Users/admin/Documents/Projects/shared_memory/scrap.py", line 116, in new_init
    'Instantiate this class using one of the classmethods.'
RuntimeError: Instantiate this class using one of the classmethods.

would rather eliminate that last bit with new_init
but i suppose it'll have to do

#

method: callable = getattr(cls, name) oh yeah, the callable here doesnt make any sense. forgot to take it out.

steep mauve
#

hey guys

#

what are you doing

#

anyone knows how to obtain a specific type from a header file in cpython with ctypes

#

in Python-ast.h there is a struct named _expr/expr_ty and it contains all expressions

#

i want to get that struct without redefining everyting inside

#

anyone knows a way to do that

glacial rampart
sullen rock
#

PEP 487, I think

brazen geyser
#

thats awesome, i didnt know __set_name__

#

was a thing

glacial rampart
#
import weakref

class WeakAttribute:
    def __get__(self, instance, owner):
        return instance.__dict__[self.name]()

    def __set__(self, instance, value):
        instance.__dict__[self.name] = weakref.ref(value)

    # this is the new initializer:
    def __set_name__(self, owner, name):
        self.name = name
class TreeNode:
    parent = WeakAttribute()

    def __init__(self, parent):
        self.parent = parent

ok yeah that is a cool use

marsh void
#

0xfor 0 still looks weird lol

brisk zenith
#

oh yeah @brazen geyser i was gonna see if i could get a really fucking chunky variable name going on, wasn't i?

brazen geyser
#

yes, dogspeed

#

max i got was somewhere between 100 billion and 1 trillion.

brisk zenith
#

what broke it? was it a memory error?

brazen geyser
#

yep, memory error on trying a trillion

brisk zenith
#

memory errors are easy to throw hardware at, overflow errors are not.

brazen geyser
#

was going up in powers of ten

brisk zenith
#

@brazen geyser was not a good idea

#

allocated 500GB to swap and managed 10,000,000,000. then my HDD began sounding like it was having an aneurysm lmao

brazen geyser
#

O_O

#

/r/tifu

edgy kelp
#

taking breaking python to the hardware level? ๐Ÿ˜›

grizzled cloak
#

talking about mem errors, i recently got one for a 40mb array...

#

no idea why

edgy kelp
#

one time occurence or always on the same array?

grizzled cloak
#

lemme check. i gave up after that haha

brisk zenith
#

if somebody can manage to run my tic-tac-toe code, i will be massively impressed

edgy kelp
#

I'm not sure I want to after reading the previous messages ๐Ÿ˜„

grizzled cloak
#

hm. seems to work now. maybe i just had something like chrome with 200 tabs eating all my ram...

#

@brisk zenith how much does it take?

brisk zenith
#

how much what?

grizzled cloak
#

ram

brazen geyser
#

sanity

brisk zenith
#

i have no idea

grizzled cloak
#

or whats the limiting factor?

brisk zenith
#

i tried running it with 800GB of swap once and the python interpreter segfaulted

#

it's a 400MB script

grizzled cloak
#

yikes

#

just tictactoe??

brisk zenith
#

just tictactoe

grizzled cloak
#

are you calculating all possible endings/??!?!?

brisk zenith
#

indeed.

grizzled cloak
#

yikes

#

how many are there?

edgy kelp
#

was that script created by you or a (non-you) machine

brisk zenith
#

i made a script to write the script

glacial rampart
#
๐Ÿ ast.dump(ast.parse('0xfor 0', mode='eval').body)
'BoolOp(op=Or(), values=[Num(n=15), Num(n=0)])'
#

nice

night quarryBOT
#

@brisk zenith, it looks like you tried to attach a file type we don't allow. Feel free to ask in #community-meta if you think this is a mistake.

edgy kelp
#

at least that ๐Ÿ˜„ Would want your editor if you had a 400mb file

brisk zenith
#

this is a mistake!

edgy kelp
#

I'd tell you to use paste but...

brisk zenith
#

haha yeah no.

#

github doesn't allow files above 100MB

grizzled cloak
#

just create many pastes hahaha

glacial rampart
#

what kind of file is it @brisk zenith

brisk zenith
#

it's a 400MB .py file. when compressed, it is only 7MB

marsh void
#

What the heck would 400 mb py file contain

edgy kelp
#

text

marsh void
#

well

#

shit ton of text, huh

night quarryBOT
#

@dense spire, it looks like you tried to attach a file type we don't allow. Feel free to ask in #community-meta if you think this is a mistake.

dense spire
#

lol

brisk zenith
#

yikes!

dense spire
#

guess I'm not big enough staffer.

brisk zenith
#

that sucks.

dense spire
#

just put it somewhere and link it?

brazen geyser
#

what a lawbreaker

brisk zenith
#

you know what, it's fine. i'll find the script which generates the tictactoe script and stick it in a paste. :D

#

thanks for trying anyways lemon, much appreciated

edgy kelp
#

I always find it surprising how fast files can get big when it's just some simple text generated by a program

brisk zenith
#

fuck the generation script was on paste.seph.club. @vague gust 0/10 wouldn't use paste.seph.club ever again.

vague gust
#

what is wrong with paste.seph.club

brisk zenith
#

my file from a year and a half ago has disappeared

#

:((((

edgy kelp
#

the url not looking like an url would be the first thing ๐Ÿ˜›

vague gust
#

that is paste.pydis you are looking for isn'tt it

brisk zenith
#

it's fine

#

i'll just rewrite the generation script

vague gust
#

hm odd

glacial rampart
sullen rock
#

Someone just showed me that the Python 3.8 := operator provides a new way of coding a C-style for loop and I'm sad now.

glacial rampart
#

show me

rare juniper
#
while i := locals().get('i', 100) - 1:
    print(i)
while (i := locals().get('i', 0) + 1) < 100:
    print(i)

lololo (technically you need to del i after the loop -- haven't found a cleaner way)

sullen rock
#

a C-style for loop that requires the un-declaration of a variable ๐Ÿ˜ฆ

rare juniper
#
i = 100
while i:=i-1:
    print(i)
#

Also an option

sick hound
#

is there a jsfuck equivalent of python

glacial rampart
#

ye

#

@rare juniper don't mind the del i at the endโ€”python has never had loop-local vars

#

there's also this which i quite like https://onelinepy.herokuapp.com/

gilded orchid
#

challenge: how many characters are needed for python to be turing complete

#

without using eval or exec

#

while:=-1 is probably TC

#

I wonder if that can be improved

cunning spindle
#
__import__("os").remove(__file__)```
brisk zenith
#

@gilded orchid is that even valid syntax?

gilded orchid
#

I'm saying how many distinct characters are needed

#

I was just listing the characters

#

(also I just realised I forgot newlines)

brisk zenith
#

oh right okay. yeah, i can see that as being turing complete.

gilded orchid
#

I think that's pretty optimal

#

since you need to be able to do infinite loops

#

(which you can't do without using way more characters with for)

#

unless maybe you could use recursive functions somehow

#

but even then you'd need def(): at a minimun, which is the same number of chars as while:

brazen geyser
#

how is while:=-1 turing complete. im not seein it.

brisk zenith
#

it's not on its own, but using any amount of just those characters is turing complete

brazen geyser
#

right thats how i mean

brisk zenith
#

you can basically make something which works like brainfuck

#

which is itself turing complete

brazen geyser
#

huh

#

ill think about it some more then

brisk zenith
#

any brainfuck program can be translated into python just by using the characters in while:=-1 and newlines.

brazen geyser
#

o.O

#

i see

brisk zenith
#

making a translator from brainfuck to a python script which uses only those characters would be quite fun

lament ibex
#

feels more beautiful because it's one line

brazen geyser
#

christ

gilded orchid
#

jesus christ

#

also yeah, I was thinking of brainfuck for those chars

#

cells can be variables using the letters and =

#

+ can be var=var--1

#

- can be var=var-1

#

[ can be while var: and then indenting 1 more for next lines

#

] can be removing 1 indentation

#

(< and > obviously aren't needed due to how we're doing our vars)

edgy kelp
#

why doesn't this work [*range(int(1E23))]

#

or at least, why does it output the error it outputs

sick hound
#

because 99999999999999991611392 is bigger than 18446744073709551616

edgy kelp
#

but can't they have any length? Works alone in a list

gilded orchid
#

18446744073709551616 is the limit for floats I think

#

and when you do 1e23 it's a float that's bigger then that

edgy kelp
#

the 1E23 is the only float there and don't think that's producing the problem as it works with ints after that

#

and setting a large step converts normally

#

for example [*range(0, int(1E23), int(1E21))]

gilded orchid
#

nvm that isn't the limit for floats

#

I'm wrong

brisk zenith
#

limit for floats is in the order of 1e308

#

at least, python's double-precision floats

snow beacon
#

It's a problem with the range function.

snow goblet
#

I think it's because 1e23 > sys.maxsize

snow beacon
#

range is implemented in C

edgy kelp
#

what exactly breaks in it? if it works with less elements

#

just confoosed here

snow beacon
#

Python ints can be arbitrary size, but range converts its argument to a C int, which can't.

edgy kelp
#

shouldn't [*range(0, int(1E23), int(1E21))] break too then?

snow beacon
#

Oh, right.

brisk zenith
#

it may be the Py_ssize_t which holds the length of the list

#

although actually

#

you'd get a memoryerror before an overflowerror there

snow beacon
#

len definitely breaks with ranges that are too big.

#

I had to reimplement it at one point.

#

Don't ask.

brisk zenith
#

why? :D

near thistle
#

This is interesting, but why is range working in this way? Seems like a bug?

#

I don't expect it yields c integers.

edgy kelp
#

With numbers that big I doubt it's a bug, just an implementation limit, but I do wonder where it breaks so that it ends with an overflow right away

near thistle
#

I wonder as well.

brisk zenith
#

i'll investigate tomorrow if you don't figure it out by then :D

snow beacon
#

I was writing a function to combine itertools.product with random.sample, designed to work with really large samples. In order to make it not need to generate every Cartesian product, I sample integers to be efficient. random.sample uses a more efficient method for range objects than any other collection, but still uses len. Thankfully, it's pure python, so I just copied and adjusted the code to find the length of ranges by simple arithmetic instead.

rare juniper
#

@gilded orchid Wouldn't space also be needed? Or is that implied?

brazen geyser
brazen geyser
#

maybe a marshmallow

distant wave
#

An alternative approach:

distant wave
#

I had it mostly written

#

then it came to a screeching halt when I couldn't determine if a function was a classmethod

#

!e ```python
class A:
@classmethod
def b(): pass

print(isinstance(A.b, classmethod))

night quarryBOT
#

@distant wave :white_check_mark: Your eval job has completed with return code 0.

False
distant wave
#

-.-

brazen geyser
#

yep, inspect.ismethod + method.__self__ is cls seems to be solid though

distant wave
#

Here's an alternate solution:

#

!e ```python
import inspect
from functools import wraps

def wrap_cls(cls):
def primary(cls_method):
@wraps(cls_method)
def wrapper(*args, **kwargs):
t = cls.init
cls.init = cls._old_init
res = cls_method(*args, **kwargs)
cls.init = t
return res

    return wrapper

return primary

def error():
raise ValueError("Don't.")

def classmethods_only(cls):
cls._old_init = cls.init
cls.init = lambda self: error()
for attr in dir(cls):
method = getattr(cls, attr)
if callable(method) and inspect.ismethod(method) and method.self is cls:
setattr(cls, attr, wrap_cls(cls)(method))

return cls

@classmethods_only
class Test(object):
def init(self):
print("test")

@classmethod
def special_init(cls):
    return cls()

def do_a_thing(self):
    print(self)

print(Test.special_init())
print(Test())

night quarryBOT
#

@distant wave :x: Your eval job has completed with return code 1.

001 | test
002 | <__main__.Test object at 0x7f51cf222510>
003 | Traceback (most recent call last):
004 |   File "<string>", line 47, in <module>
005 |   File "<string>", line 25, in <lambda>
006 |   File "<string>", line 20, in error
007 | ValueError: Don't.
distant wave
#
instantiation without metaclass: 0.000424896000000001
instantiation with metaclass: 0.680442438
instantiation with classmethods_only: 0.001014326999999926
#

Do note that my solution does not support the following:

class A:
    def __init__(self): pass

A.b = classmethod(lambda cls: cls())
#

Although if you do so, you could always call A = classmethods_only(A) after all the adjustments

distant wave
#

I smell an alternate solution that's cleaner and faster, but I'm not going to write it

#

I suspect you can overwrite __self__ inside the classmethod decorated function

brazen geyser
#

might have some threadsafety issues due to the swapping in/out of __init__ but that's a problem for another time

distant wave
#

To point at another or proxy class with a different __init__

#

yeah

brazen geyser
#

overwriting __self__ sounds like the darkest of dark magics

distant wave
#

I mean, this code up there that swaps out __init__ whenever you call a classmethod is not what you'd call white magic >.>

brazen geyser
#

tru ๐Ÿ˜›

distant wave
#

Imo, best of cases would be a custom decorator that mimics @classmethod

#

With the proxy with a new init, or w/e

brazen geyser
#

i hear ya

distant wave
#

good luck!

#

hm...

brazen geyser
#

great work ๐Ÿ˜„

distant wave
#

I have an evil idea

brazen geyser
#

where do i send this marshamallow

#

btw

distant wave
#
import inspect
from functools import wraps

def wrap_cls(cls, old_init):
    def primary(cls_method):
        @wraps(cls_method)
        def wrapper(*args, **kwargs):
            t = cls.__init__
            cls.__init__ = old_init
            res = cls_method(*args, **kwargs)
            cls.__init__ = t
            return res

        return wrapper

    return primary


def error():
    raise ValueError("Don't.")


def classmethods_only(cls):
    old_init = cls.__init__
    cls.__init__ = lambda self: error()
    for attr in dir(cls):
        method = getattr(cls, attr)
        if callable(method) and inspect.ismethod(method) and method.__self__ is cls:
            setattr(cls, attr, wrap_cls(cls, old_init)(method))

    return cls


@classmethods_only
class Test(object):
    def __init__(self):
        print("test")

    @classmethod
    def special_init(cls):
        return cls()

    def do_a_thing(self):
        print(self)
brazen geyser
#

i worry about the potential implications for super()

distant wave
#

Now we bind the old init function into a functions namespace, so it's not lurking anywhere at all, mwhahaha

#

hm

#

What about it?

brazen geyser
#

not sure, but i feel like something about it's bound to become royally fucked up

distant wave
#

It was always special

brazen geyser
#

potentially incorrect mro

distant wave
#

Oh, not in this case at least

#

we're not touching the MRO, just the definitions of the current class

#

We're just overwriting the __init__ attribute at definition time

brazen geyser
#

i like the name classmethods_only much better btw

distant wave
#

glad you do :P

thin trout
brazen geyser
#

๐Ÿ˜„ well if there are parts you want me to explain let me know @thin trout

thin trout
#

Okay I think I'm gonna take my breakfast, think a bit about it and I will probably have dozen of question about it ๐Ÿ˜„. I really appreciate the offer

steep mauve
#

juanita

#

how to obtain a specific type from a header file in cpython with ctypes
in Python-ast.h there is a struct named _expr/expr_ty and it contains all expressions
i want to get that struct without redefining everyting inside
anyone knows a way to do that

livid seal
#

@steep mauve why do you not want to use the ast module?

steep mauve
#

auscompgeek Python-ast.c doesnt expose all of its API to ast module

#

also i need that struct not a ast.expr class

grave rover
#

@steep mauve can you explain what you want to do?

steep mauve
#

there are internal functions used for AST with PyAST_ prefix

#

what i want is using them with ctypes

#

my_function = ctypes.pythonapi.PyAST_foobar

grave rover
#

๐Ÿค”

steep mauve
#

but i need to set argtype to expr_ty / _expr struct defined in Python-ast.h

grave rover
#

and what for

#

can you give an example in code?

steep mauve
#

sure

grave rover
#

pseudocode works too

steep mauve
#
import ctypes
myfunction = ctypes.pythonapi._PyAST_Optimize
myfunction.argtypes = [get_struct("mod_ty", "Python-ast.h"), ...]
#
get_struct(struct_name: str, header_file: PathLike) -> ctypes.Struct
grave rover
#

๐Ÿค”

#

I think you'd have to either parse the header and dynamically recreate the struct in python as ctypes.Structure, or just manually create a ctypes.Structure

#

as long as it's the same format it should work just fine

steep mauve
#

it is kind a big struct (expr_ty)

#

it is union of all ast expression nodes

#

with all fields

grave rover
#

hm

#

you'd probably have to parse it then

steep mauve
#

๐Ÿ˜ฆ

zealous widget
#

i was doing the spiral kata on codewars and i had a tuple of directions ((0, 1), (1, 0), (0, -1), (-1, 0)) and a variable direction that i would index the tuple with, and i kept doing the standard direction = (direction + 1) % 4 thing that one usually does, but then i thought i should just make a modtuple class:

class modtuple(tuple):
    def __getitem__(self, key):
        if isinstance(key, int):
            return super().__getitem__(key % len(self))
        if isinstance(key, slice):
            start = key.start % len(self)
            stop = key.stop % len(self)
            if start < stop:
                return super().__getitem__(slice(start, stop))
            return super().__getitem__(slice(start, None)) + super().__getitem__(slice(None, stop))

but this only covers the cases i needed, how about a full fledged __getitem__ for this type of tuple

#

i realize that itertools has cycle, but i needed to index the tuple to look ahead, without calling next a bunch of times needlessly

#
In [197]: a = modtuple((1,2,3,4,5,6,7,8))

In [198]: a[10]
Out[198]: 3

In [199]: a[10:5]
Out[199]: (3, 4, 5)

In [200]: a[5:2]
Out[200]: (6, 7, 8, 1, 2)

sample output

proper vault
#

width, height = 8,6
list(dict.fromkeys([point for dir_zip in zip(*(t(width, height)+[[(1,)]] for t in map(lambda p,q,q1,r,s: lambda w, h: [list(zip(*(map(q1(h), ex[::q]), [r(w,h,a)] * len(ex))[::s])) for a, ex in enumerate((lambda x: [range(a, b) for a, b in zip(range(x), range(x, -1, -1)) if len(range(a, b))])((h if s < 0 else w) - p))], (0,1,1,2), (1,1,-1,1), ( lambda x:lambda y:y, lambda h: lambda u: u + 1, lambda x:lambda y:y, lambda h: lambda u: h - u - 2 ), ( lambda w, h, x: x, lambda w, h, x: w - 1 - x, lambda w, h, x: h - 1 - x, lambda w,h, x: x ), (1,-1,1,-1) ))) for point_l in dir_zip for point in point_l if len(point) > 1]))
pure dew
#

who says programmers don't know how to have fun

>>> what_are_you_doing_in_my_swamp = q("what_are_you_doing_in_my_swamp", "get out me swamp")
>>> what_are_you_doing_in_my_swamp
Use what_are_you_doing_in_my_swamp() or get out me swamp to exit
>>> type(what_are_you_doing_in_my_swamp)
<class '_sitebuiltins.Quitter'>
>>> 
pine edge
#

i hadn't thought about the exit message's implication, but it really is just an object that exists and has a repr

#

why would there even be a constructor that lets you provide a different set of strings

#

maybe you could use it for international purposes

#

but it still has the words "Use" and "or" hardcoded in so good luck using that for translation

snow beacon
#

I believe it's so different applications can provide different names and hotkeys for the quitter.

pine edge
#

that's oddly specific for a dedicated constructor

#

especially when you can just

#
>>> exit = type("quitter 2 electric boogaloo",(object,),{"__repr__":lambda s:"exit is a function dummy","__call__":lambda s:__import__("sys").exit()})()
>>> exit
exit is a function dummy
>>> exit()
snow beacon
#

Ugh, that looks like the sort of thing that belongs in this channel.

sick hound
#

well there's exit and quit ```py

exit
Use exit() or Ctrl-Z plus Return to exit
quit
Use quit() or Ctrl-Z plus Return to exit```

pine edge
#

that'd explain the name part

#

since python makes two of them

#

and the other part is probably platform dependent

#

based on how whatever you're running that on is a different key combo

#

understandable

snow beacon
#

I think they're in the site module.

#

Not all Python implementations have them.

grizzled cloak
#

hey guys, someone posted a question from a contest in one of the help channels and i found it quite fun, so here it is:
write a function that finds out if a number is a 'vampire number': https://en.wikipedia.org/wiki/Vampire_number

#

it should be as fast as possible

#

they said you could even win discord nitro if you win!

#

i used this number to benchmark because all the examples they give are finished too fast.
24959017348650
in .2 seconds

zealous widget
#

is there something better than multiplying all combinations of half its digits

#

...or i guess you just run over permutations and split that in half?

grizzled cloak
#

i calculated the factors of the number with len num_digits/2 and then checked those

#

its a lot faster for large numbers

#

but not so much for small ones

#

i think

zealous widget
#

i'm making a multiset combination function

#

cause i can't find one in python

#

weird

grizzled cloak
#

yeah. i couldnt find any either

#

decided to go another route then

zealous widget
#

nah, multiset combinations is gonna be the fastest

#

you only have to generate half of them too

grizzled cloak
#

can you send me the function if you come up with one?

zealous widget
#

i'll put it up

proper vault
#

I got it in .5s using permutations, but different machines, so the numbers are meaningless

marsh void
#

Moving from this theme, is it possible to create custom traceback message?

proper vault
#
  File "<stdin>", line 1, in <module>
ValueError: Hello``` at which point do you want the custom message?
grizzled cloak
#

@zealous widget and hows it going?

brazen geyser
#

why are they called vampire numbers

proper vault
#

they have 2 fangs

grizzled cloak
#

^

#

very spooooky

#

๐Ÿ‘ป

marsh void
#

@proper vault I wanna show custom stuff in the traceback lol

#
Traceback (oh hey it is custom):
    Oops! Some error occured...
ValueError: Hello```
#

Something like this

proper vault
#

Thinking ASCII control characters in the error message may get you somewhere

marsh void
#

Or just with_traceback but I need to instantiate <class 'traceback'> or something

proper vault
#
def is_number_small(x):
    y = int(x*1.0)
    return x is y
finite orbit
#

Hi, I would like to have an information, in the panda 3D engine, they would like to change the variable tp_dict to check for some typing. But in the documentation says that it's bad to tamper with tp_dict and they don't say why. Does someone know why using tp_dict is bad?
Btw, the docs about tp_dict is here: https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_dict

sullen rock
#

@proper vault that's cool! You can save a few characters and a temporary variable:

def is_number_small(x):
    return x is x*1
zealous widget
#

after generating multiset combinations, i realize i'll also need multiset permutations and i'll have to handle special cases where 0 is at the beginning of a permutation

#

my code is quite lengthy already, problem is trickier than it seems if you want to do it efficiently

proper vault
#

I did iterators

rugged sparrow
#

@marsh void ```py
import traceback, sys, colorama, termcolor

colorama.init()

def excepthook(ext, exc, tb):
tb_list = traceback.format_exception(ext, exc, tb)
tb_list[0] = tb_list[0].replace('Traceback', termcolor.colored('Traceback', 'blue', attrs=['bold']))
if 'File' in tb_list[0]:
tb_list[0] = termcolor.colored(tb_list[0], 'blue', attrs=['bold'])
for line in range(len(tb_list[1:-1])):
tb_list[line+1] = termcolor.colored(tb_list[line+1], 'blue')
tb_list[-1] = tb_list[-1].replace(ext.name, termcolor.colored(ext.name, 'red', attrs=['bold']))
tb_list[-1] = tb_list[-1].replace(exc.args[0], termcolor.colored(exc.args[0], 'yellow', attrs=['bold']))
print(*tb_list, end='')

sys.excepthook = excepthook``` i saw you were asking about custom exceptions, this code adds colors to them

marsh void
#

Very epic

lament ibex
#

Nice, even better look than IPython's implementation

#

There's a module colored-traceback on PyPi too

#

On the topic of excepthooks I dug up this script I made that lets you type bare words (doesn't work within functions though)

import sys, traceback

def excepthook(e_type, value, e_traceback):
    if e_type is SyntaxError:
        bare_words = traceback.format_exception(e_type, value, e_traceback)[-3].strip()
        print(bare_words.upper())
    else:
        sys.__excepthook__(e_type, value, e_traceback)

sys.excepthook = excepthook
exec("very useful thing")
grave rover
#

Do we know of ways to abuse sys.settrace yet?

snow beacon
#

I believe one of the challenges on GitHub, specifically the Maybe one, had a submission using it.

sick hound
#
import sys,random
m='Maybe'
def t(f,e,a):
 # 3.7 ONLY: f.f_trace_opcodes=True
 if e=='call':
  c=f.f_code
  for i,o in enumerate(c.co_code[::2]):
   x=c.co_code[i*2+1]
   if o in b'Z[ab'and c.co_names[x]==m or o in b'}~'and c.co_varnames[x]==m:exit()
 f.f_locals[m]=bool(random.choice([1,0]))
 return t
sys.settrace(t)```
brazen geyser
#

i think there's a goto module that uses settrace

marsh void
#

cool

brazen geyser
#

not sure thats the word ๐Ÿ˜›

last locust
#
import random
def maybe(*a):
    return random.choice([any, all])([*a])```How can I make this less chars? Aside from renaming the function to like `m`
grizzled cloak
#
import random
def maybe(*a):
    return [any, all][random.randint(0,1)]([*a])```
#

dont know if thats shorter

lament ibex
#
maybe=lambda*a:random.choice((any,all))([*a])
grizzled cloak
#

why a tuple instead of a list here?

lament ibex
#

No real reason. Just something I use by default because it's not going to be mutated

edgy kelp
#

the question should be why a list instead of a tuple ๐Ÿ˜„

lament ibex
#

My question though is why can't you use starred expressions with tuples

edgy kelp
#
>>> (*range(5),)
(0, 1, 2, 3, 4)
lament ibex
#

oh of course ๐Ÿคฆ

#

doesn't help reduce chars here though

edgy kelp
#

it also works without the parenthses but in your case the tuple takes the parentheses around like its own I think

lament ibex
#

Yeah no I just had a brainfart

distant wave
#

Today I learned:

#
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> a[:0] = a     # Insert (a copy of) itself at the beginning
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]
gilded orchid
#

wow cool

lament ibex
#

I prefer a[0:0] = a because it looks like googly eyes

brazen geyser
#

maybe=lambda*a:random.choice((any,all))([*a])
you can pass a by itself here

#

so maybe=lambda*a:random.choice((any,all))(a)

lament ibex
#

Ah true

snow beacon
#

How random does it need to be?

lament ibex
snow beacon
#

I've used something like id(a)&8>0 in the past.

#

That gives 0 or 1

#

It's implementation dependent.

brazen geyser
#

how bout just id(a)&1

snow beacon
#

No, I tried that

#

I think the lowest bits were always unset because it's byte-aligned

brazen geyser
#

huh

#

TIL

#
>>> bin(id([1,2,3]))
'0b10110111111111101000011100011010110001000'
>>> bin(id([1,2,3]))
'0b10110111111111101000011100011011010001000'
>>> bin(id([1,2,3]))
'0b10110111111111101000001011010011001001000'
>>> bin(id([1,2,3]))
'0b10110111111111101000001111010111101001000'
>>> bin(id([1,2,3]))
'0b10110111111111101000011100011000100001000'
>>> bin(id([1,2,3]))
'0b10110111111111101000011100000110001001000'
>>> 
#

highest bits seem to be pretty much always the same as well

#

oh yeah but then again thatd make sense as the id count goes up

#

oops ๐Ÿคฆ

gilded orchid
#

Challenge: create Pyth's infinite_iterator function, that takes a number and endlessly iterates incrementing the number each time, eg:

for i in infinite_iterator(7):
 print(i)

will start with 7 and endlessly output nubers adding 1 each time

#

(I don't really know how'd you do this, and maybe it'll be really easy)

brazen geyser
#

wouldnt that just be a simple generator?

#
def infinite_iterator(n):
    while True:
        yield n
        n += 1
gilded orchid
#

oh yeah wow I'm bad

rugged sparrow
#

@gilded orchid this does it with the new walrus py (lambda n,y=[]:map(lambda x:(y.append(x+1),y[-1])[1],(y:=y or [n])))

#
(lambda n:iter(lambda l=[n]:(l.append(l[0]+1),l.pop(0))[1],''))``` and this does it by abusing iter
brazen geyser
#

abusing both

lambda n:((n,n:=n+1)[0] for _ in iter(int,1))
crystal mica
#

I love that iter(int, 1) lol

rugged sparrow
#

i think its the smallest infinite iterator

lament ibex
#

Why do you have (n,n:=n+1)[0]? n:=n+1 works by itself

brazen geyser
#

to yield the value of n passed in as param

#

otherwise it'll start from n+1

rugged sparrow
#
infinite_iterator = (lambda n:map(lambda l:l[0],enumerate(iter(int,1),n)))``` another way to do it
gilded orchid
#

I can't test this, but can't you do n or n:=n+1 instead of (n,n:=n+1)[0]

#

(to save 1 byte)

#

@brazen geyser

brazen geyser
#

think thatll short circuit

rugged sparrow
#

the n:=n+1 wouldnt be calculated

brazen geyser
#

yep

lament ibex
#

comes up as cannot use named assignment with operator for me

gilded orchid
#

oh right

#

would n:=n+1 and n work (although it isn't shroter)

wind maple
#

@gilded orchid itertools.count I win

brazen geyser
#

with some parentheses around n:=n+1 thatll work i think

gilded orchid
#

oh ok

lament ibex
#

it just keeps outputting the initial value

#

haven't worked out why yet

brazen geyser
#

oh yeah

#

n:=n+1 is gonna be computed first

#

so nevermind

#
>>> 1 and 2
2
>>> 3 and 1
1
>>> 
#

seems to always return the rhs

lament ibex
#

Wait I still don't get why it doesn't iterate though

brazen geyser
#

which one?

lament ibex
#

the one with and

brazen geyser
#

it doesnt? o.O

#

what did you pass in as n?

lament ibex
#

just 7, any number

rugged sparrow
#
infinite_iterator = lambda n:(i for i,_ in enumerate(iter(int,1), n))``` this works too
sick hound
#

and returns the left if it's false and the right if the left is ture

brazen geyser
#
>>> v = lambda n:((n:=n+1) and n for _ in iter(int,1))
>>> k = v(7)
>>> next(k)
8
>>> next(k)
9
>>> next(k)
10
>>> next(k)
11
>>> 
#

@lament ibex

sick hound
#
>>> 0 and 'hello'
0
>>> '' and 'hello'
''
>>> 4 and 'hello'
'hello'
>>> 4 and 'goodbye'
'goodbye'```
lament ibex
#

nevermind I did a stupid with the brackets

gilded orchid
#

another challenge: make is so you can index ints

rugged sparrow
#

like 1[1]?

gilded orchid
#

(eg: 4522[1] would be 5)

brazen geyser
#

lel ๐Ÿ˜›

wind maple
#

oh rip

#

python 2 docs

#

:pathetic:

brazen geyser
#

first result on google

#

blame google

gilded orchid
#

yeah google always gives py 2 docs

#

idk why

edgy kelp
#

it's worse if it gets you 2.3 docs where you can't just click to get to the newer

brazen geyser
#
>>> class IndexableInt(int):
    def __getitem__(self, item):
        return int(str(self)[item])

    
>>> IndexableInt(12)[1]
2
>>> 

does this count @gilded orchid

#

nah it's lame. i take it back.

#

it shouldnt count

lament ibex
#

I found an evil library that does this

#
>>> from forbiddenfruit import curse
>>> def intindex(self, x):
...     return int(str(self)[x])
... 
>>> curse(int, "__getitem__", intindex)
>>> 1234[2]
3
>>> 
brisk zenith
#

yeah forbiddenfruit is a thing

brazen geyser
#

i tried that with __iter__ and it failed silently ๐Ÿ˜ฆ

#

maybe it's been patched

lament ibex
#

this is amazing why haven't I heard of it earlier

#

so many great methods I can add to built-ins now yayh

brazen geyser
#
>>> from forbiddenfruit import curse
>>> def intiter(self):
    yield from range(self)

    
>>> curse(int, '__iter__', intiter)
>>> for i in 3:
    print(i)

    
Traceback (most recent call last):
  File "<pyshell#285>", line 1, in <module>
    for i in 3:
TypeError: 'int' object is not iterable
>>> 

ffs

lament ibex
#

What do you mean by patched, it was working before?

brazen geyser
#

when i saw your example i got my hopes up that it would work now

#

but i think __iter__ might be a special case so it might take some extra work to get going

zealous widget
#

dunno, do you need a __next__ method too?

#

seems like you shouldn't in this case

brazen geyser
#
>>> class Test:
    def __iter__(self):
        yield from ()

        
>>> iter(Test())
<generator object Test.__iter__ at 0x0000016FFD5394C8>
>>> 
sick hound
#
from ctypes import*
d=(v:=c_void_p*3)()
d[1]=cast(CFUNCTYPE(p:=py_object,p,p)(lambda s,i:int(str(s)[i])),v)
(v*52).from_address(id(int))[14]=cast(d,v)```
rugged sparrow
#
chronos@localhost ~ $ python
Python 3.8.0 (default, Oct 14 2019, 20:32:20) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from forbiddenfruit import curse
>>> curse(int,'__getitem__', lambda self, index:str(self)[index])
>>> 100[0]
'1'
>>> 100[3]
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 237, in 'calling callback function'
  File "/usr/local/lib/python3.8/site-packages/forbiddenfruit/__init__.py", line 359, in wrapper
    return func(*args, **kwargs)
  File "<stdin>", line 1, in <lambda>
IndexError: string index out of range
Segmentation fault (core dumped)
chronos@localhost ~ $ ``` so forbiddenfruit works in 3.8. but python doesnt like exceptions in cursed methods
lament ibex
#

Honestly we deserve a segfault for doing this ๐Ÿ˜„

#

What does that do @sick hound

sick hound
#

@lament ibex makes ints indexable

#

no libraries required except ctypes

#

also it's python 3.8

#

oh wait actually we messed it up

#
from ctypes import*
d=((v:=c_void_p)*3)()
d[1]=cast(CFUNCTYPE(p:=py_object,p,p)(lambda s,i:int(str(s)[i])),v)
(v*52).from_address(id(int))[14]=cast(d,v)```
#

there

#

slices work too ```py

from ctypes import*
d=((v:=c_void_p)3)()
d[1]=cast(CFUNCTYPE(p:=py_object,p,p)(lambda s,i:int(str(s)[i])),v)
(v
52).from_address(id(int))[14]=cast(d,v)
125[1]
2
12345[2:]
<stdin>:1: SyntaxWarning: 'int' object is not subscriptable; perhaps you missed a comma?
345```

#

it doesn't work if it's out of range though

#
>>> 0[4]
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 237, in 'calling callback function'
  File "<stdin>", line 1, in <lambda>
IndexError: string index out of range```
#

then segfault

lament ibex
#

lmao love that the warning comes up

rugged sparrow
#

weird that the syntax warning doesnt come up unless youre slicing

#

also how do you know the index on the c_void_p array?

#

@sick hound

sick hound
rugged sparrow
#

ah

#

sweet

grizzled cloak
#

@lament ibex to readable. try this!:

import math
from forbiddenfruit import curse
curse(int, {}.__getitem__.__name__, lambda self, x: [(self//(10**i))%10 for i in range(int(math.log10(self)+1)-1,-1,-1)][x])
146[1]
Out[5]: 4```
brazen geyser
#

"tp slots" heh

lament ibex
#

I really want to get around to understanding this ctypes magic

grizzled cloak
#

oops. had some spaces in there ๐Ÿ˜‰

lament ibex
#

lol

#

Can someone get iter working with that ctypes wizardry, I'd love to see it working

gilded orchid
#

also you can actually see a string in there

#

unacceptable

grizzled cloak
#

oh. yikes

#

@gilded orchid fixed

lament ibex
#

Random question, and not sure where to ask this but does anyone know of any entertaining (esoteric) Python talks? I'm thinking talks similar to Wat, PowerPoint turing machine/fractals and so on.

zealous widget
#

David Beazley - Lambda Calculus from the Ground Up - PyCon 2019

lament ibex
#

Thanks I'll have a look

brazen geyser
#

is there a faster hacky way to calculate int(log2(value))?

#

found it. int.bit_length - 1

brazen geyser
#

though not hacky at all of course

rugged sparrow
#

@marsh void

marsh void
#

Danke wowers

#

Dunder overloading is a bit long, haha @rugged sparrow

rugged sparrow
#

Yeah

marsh void
#

plus uhm, those _fields_ like damn xdd

#

And yeah that stuff is only CPython as far as I get it

rugged sparrow
#

Yeah

#

Just cotton

#

*cpython

proper vault
#

seems like you cannot curse __call__

rugged sparrow
#

not with forbidden fruit

sick hound
#
>>> from ctypes import*
>>> (c_void_p*52).from_address(id(int))[16]=cast(CFUNCTYPE(py_object,py_object,py_object,c_void_p)(lambda s,*_:s),c_void_p)
>>> 5()
<stdin>:1: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?
5```
marsh void
#

lmao

rugged sparrow
#
import ctypes
from forbiddenfruit import curse

class refStruct(ctypes.Structure):
   _fields_ = [('refcnt', ctypes.c_long)]
   
def getRefStruct(obj):
   return refStruct.from_address(id(obj))
   
def getPyObj(adr):
   return ctypes.py_object.from_address(adr)

def __setitem__(self, index, val):
      accindex = len(self) + index if index < 0 else index
      if accindex > (len(self) - 1):
         ctypes.pythonapi.PyErr_SetString(ctypes.py_object(IndexError), b'tuple index out of range')
         return -1
      else:
         getRefStruct(self[accindex]).refcnt -= 1
         getRefStruct(val).refcnt += 1
         getPyObj(id(self) + 24 + accindex * 8).value = val
         return 0
      
curse(tuple, '__setitem__', __setitem__)```
#

@sick hound any idea why this doesnt set an error properly?

#
>>> x = (0,)
>>> x[1] = 1
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 237, in 'calling callback function'
  File "/usr/local/lib/python3.8/site-packages/forbiddenfruit/__init__.py", line 359, in wrapper
    return func(*args, **kwargs)
  File "<string>", line 16, in __setitem__
IndexError: tuple index out of range
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
SystemError: error return without exception set
>>> ```
sick hound
#

python might be messing with the error?

proper vault
#

anywhere I can read up on how to do the ctypes hackery?

lament ibex
#

^ I would be very interested too

#

Besides just trial and error

sick hound
#

cpython docs

#

generally you'll want to use the id of whatever you want to edit as an address

marsh void
#

*Mostly in CPython.

crystal mica
#

@zealous widget

#

!e ```py
from random import choices
from string import ascii_uppercase, digits

print('-'.join(['{}' * 4] * 4).format(*choices(ascii_uppercase + digits, k=16)))

night quarryBOT
#

@crystal mica :white_check_mark: Your eval job has completed with return code 0.

TXVW-TQZC-KZHH-JSSR
crystal mica
#

Come at me

#

changing this to a n * n is trivial

zealous widget
#
print(*("".join(choices(string.ascii_uppercase,k=4))for _ in"."*4),sep="-")
#

did i save any bytes

rugged sparrow
#

@zealous widget โ€œ.โ€*4 is shorter than โ€œ....โ€

zealous widget
#

one byte, nice

rugged sparrow
#

ยฏ_(ใƒ„)_/ยฏ

#

Remove space after in

#

Should still be valid

snow beacon
#

Why string. for ascii_uppercase, yet no random?

zealous widget
#

because of my imports

#

whenever i import choice or choices it's almost always from random import choice, choices

rugged sparrow
#

@zealous widget why not use py [*map(chr,range(65,91))] instead of string.ascii_uppercase

zealous widget
#

gross

rugged sparrow
#

๐Ÿ™‚

zealous widget
#

i dont think you have to unpack it to pass it to choices

rugged sparrow
#

you do

#

choices needs to get the len of the passed object

#

map objs have no len

zealous widget
#

i thought it unpacked it itself

rugged sparrow
#
>>> choices([*map(chr,range(65,91))],k=4)
['A', 'Y', 'C', 'T']
>>> choices(map(chr,range(65,91)),k=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.8/random.py", line 394, in choices
    n = len(population)
TypeError: object of type 'map' has no len()
>>> ```
zealous widget
#

damn, choices is bugged, i'm writing my senator

rugged sparrow
#
print(*("".join(__import__('random').choices([*map(chr,range(65,91))],k=4))for _ in"."*4),sep="-")```
#

@zealous widget i think thats as small as i can get it

crystal mica
#

I have a new definition of dangerous people on the internet now

rugged sparrow
#

haha

#

just wait till tomorrow when im actually awake. cause i want to try and get it smaller

zealous widget
#

all my thinking is on a different project

rugged sparrow
#

@crystal mica i wrote code earlier today that makes tuples mutable like x[0] = 1

#

still gets a weird SystemError i need to debug before i oneline it

vestal solstice
#
a=__import__('random').choices([*map(chr,range(65,91))],k=19)
a[4::5]='---'
print(''.join(a))
#

@rugged sparrow 5 shorter

zealous widget
#

a[4::5]='-'*3 not shorter, but looks more esoteric

proper vault
#

Wouldn't import random as r be shorter

crystal mica
#

I doubt it if you just need to call it once

#
__import__('random')```vs```py
import random as r```and then call `r.`
#

roughly the same bytes I think

sick hound
#

yeah but you can't exaactly do in one line, though it doesn't seem to be what you are doing

crystal mica
#

you cannot do it in one line, yep

snow beacon
#

from random import*?

crystal mica
#

Would that be shorter?py from random import* import random as rr.

#

oh it is shorter by 1 byte!

zealous widget
#

well, unless you count newlines as 2bytes

brazen geyser
#

you can use ;

#

import random as r; print(r.bleh)

#

well, minus the space after

proper vault
#

That does not count as a oneliner

brazen geyser
#

why not

grizzled cloak
#

im pretty sure ; is seen as a newline in python

#

kinda like writing its all in a string with \n and then evaling that

vestal solstice
#

no, someone showed recently that it breaks if you e.g. have while

#

for some reason

#
print(3); while False: print(1)
```that's invalid
grizzled cloak
#

yeah i think you can only have a expression after it

#

similarly to how this doesn't work:

lambda x: while True: pass```
brazen geyser
#

per suite

thin trout
#

print(__import__('random').bleh)) it is an oneliner?

#

My bad that doesn't work

brazen geyser
#

oh wait thats just plain old bnf, not ebnf

rugged sparrow
#
>>> curse(int, '__matmul__', lambda x,y:range(x,y))
>>> [*0@10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ``` forbiddenfruit is so cool
marsh void
#

haha true

#

Except that CPYTHON ONLY

old flint
#

is there a way to open a โ€œcontextโ€ inline?

#

instead of having to do (e.g.) with context_func():

#

to do something inline do(context_func)

#

but still get the benefit of like finally: logic when the outer scope is exited

edgy kelp
#

well you can pass the compound statements like above

#

for other ways I'm far from being esoteric enough ๐Ÿ˜›

old flint
#

what do you mean?

snow beacon
#

There might be a built-in that lets you pass it a function to put in with, but I can't think of any.

old flint
#

or is there any functionality to detect when the scope that an object was created in is being exited

edgy kelp
#

you could just add an another with arg for a context manager that would only do that

#

and link the context manager object to the one where you want to know about it

edgy kelp
#

you can do this with a with for the scope

class MyContext:
    def __init__(self, tracked_obj):
        self.tracked_obj = tracked_obj

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("with of", repr(self.tracked_obj), "at", hex(id(self.tracked_obj)), "exited")


def do_stuff(*_, **__): pass


with open("DELETEMELATERTHANKYOUVERYMUCH", "w") as obj,\
     MyContext(obj):
    pass

with MyContext(myvar := 5):
    do_stuff(myvar)

if I understood you right you can just create a decorator that applies this

old flint
#

ah but you'd still need MyContext as the outer context though

#

I guess that works to only have to do it once

#

but how do we get it down to zero...

edgy kelp
#

you don't really add it unless you want to track everything

#

Now that I think about it, it'd be easier and nicer for the tracked vars to just be almost that you can append to after the with instead of walrusing it in

crystal mica
#

@rugged sparrow @zealous widget contender from @red timber

#
print(*[(chr(__import__('random').randint(65,90)),'-')[1>>i%5]for i in range(1,20)],sep='')```
red timber
#

shut up dude

crystal mica
#

Come at me

red timber
#

-3-

crystal mica
#

It's a smart usage of modulus to get that -

#
print(*[(chr(__import__('random').randint(65,90)),'-')[1>>i%5]for i in range(1,20)],sep='')
print(*("".join(__import__('random').choices([*map(chr,range(65,91))],k=4))for _ in"."*4),sep="-")```shorter!
#

screw u discord

snow beacon
#

1>>i%5 -> i%5<1

#

Or, even better, 1>i%5

#

It's just the removal of a >

#

Then it's slightly more esoteric, but same length to do python print(*[(chr(__import__('random').randint(65,90))+'-')[1>-~i%5]for i in range(19)],sep='')

#
print(*[(chr(__import__('random').randint(65,90))+'-')[i%5>3]for i in range(19)],sep='')``` looks to be even shorter.
#

Not shorter, just weirder: python print(*[f"{chr(__import__('random').randint(65,90))}-"[i%5>3]for i in range(19)],sep='')

distant wave
#

i&3>2 is a faster check

thin trout
#

i&3>2 is similar to i % 3 == 0?

distant wave
#

i % 4 == 3

#

since it's &, as the last two binary digits loop through 00, 01, 10, and 11, it returns 0, 1, 2, 3 ( masking the last two binary digits )

#

hm, that's wrong since it returns 3 true then 1 false

brazen geyser
#
n=[chr(65+(i&25))for i in __import__('os').urandom(19)];n[4::5]='---';print(*n,sep='')
#

does this count

zealous widget
#

christ whats happening

fallow storm
#

Is there a way to override the behavior of pass?

vestal solstice
#

&25 is not % 26

#

it's only 8 possibilities

brazen geyser
#
n=[chr(65+i%26)for i in __import__('os').urandom(19)];n[4::5]='---';print(*n,sep='')

better?

#

@fallow storm im guessing youd have to find some way to intercept it at the compilation stage. pass doesn't result in any bytecode being generated.

#

tl;dr: most likely not

#

maybe using sys.settrace, go through the code of a function before it's executed, replace each pass with something else, recompile the function, then run that instead.

or a decorator that does the same, etc.

#

so there's your in for possibly intercepting pass

#

not sure if it'll actually be traced or not

grave rover
#

Challenge: Solitaire

Recently, Zachtronics games have released their new game, MOLEK-SYNTEZ, and it includes a Solitaire variant (rules attached)

The input for your function will be a List[List[int]] where int is a number representing the value of the card (6-14, V=11, D=12, K=13, T=14) and the inner list is one of the columns. There are only 6 columns.
Note: when a stack is completed, the column becomes unusable.

The output should be the moves required to solve the board, if possible.
If impossible, return False.
Bonus: If possible without cheating, return a solution doing that.
Bonus: Fastest execution.

For any additional questions, feel free to send them to me.

#

I'll try making a PoC implementation

edgy kelp
#

Think freecell would be nicer with the almost all solvable boards

brisk zenith
#

@grave rover looks good to me, sure i can pin it. it'll be up to you to get people to notice it and stuff though :)

grave rover
slim pecan
#

Hmm

#

I have no idea

#

Haha

grave rover
#

It's an event and organized by a community member :P

slim pecan
#

I'm not exactly overlord of that system, I just make use of it

formal sandal
edgy kelp
#

I stopped after having trouble to get games with players that weren't bots, how is it now?

formal sandal
#

I don't think I ever encounter bots, I usually play with real people only.

#

Are bots somehow marked explicitly?

edgy kelp
#

only in their profile

formal sandal
#

I came 2nd in one round, and now I'm back at the 10th place :(

thin trout
#

What is Clash of Code?

#

Looks fun

formal sandal
#

You compete in either speed or code-golfing.

snow beacon
#

There's also a bit of inductive reasoning for half of the speed challenges, because you don't get given a problem, just some valid outputs for certain inputs.

#

The other half of the speed challenges are normal.

wind maple
#

I don't really get why they bunch all 3 together

thin trout
#

Ooh codingame, I played at this thing

lament ibex
#

Tried one, no one got more than 50% on the first problem lol

#

The reverse mode is hard

formal sandal
#

It's not bad if the problem is hard, but I once saw a "reverse" problem where the I/O pattern was very ambiguous. All the test inputs were correct, but some of the hidden tests failed.

lament ibex
#

Man this is actually fun

#

Why haven't I heard of it before ๐Ÿ˜„

lament ibex
#

How does the leaderboard work? There's two numbers but no explanation for what they are, I assume the 2nd one is no. of games played but the first one idk

snow beacon
#

Score? Wins?

formal sandal
#

It's the "score". It depends on the amount of rounds you play and the place you take in the round-local leaderboards.

#

It also somehow decreases with time.

#

I guess it uses some smart algorithm so that if you become better over time, you get closer to the 1st place.

lament ibex
#

Ah interesting, cause I played for an hour-ish (got a bit sucked in lol) and somehow ended up 128th in the world, which didn't make sense to me at the time

formal sandal
#

If you are a new and active player and get decent results, you will get pretty high in short-term, I think.

#

It's not hard to get in the top 3 of your country.

marsh void
#

If it is not Russia @formal sandal haha

formal sandal
#

Russia is no exception :)

lament ibex
#

Haha yep I'm in Australia and got first really quickly, we only have 25M people here

marsh void
#

@formal sandal haha, I am probably gonna be around top 10 cuz probably not skilled enough yet

formal sandal
#
def is_even(n):
    try:
        eval('"' + '\\'*abs(n) + '"')
        return True
    except:
        return False
thin trout
formal sandal
#
def is_even(n):
    try:
        eval('" '*abs(n))
        return True
    except:
        return False
zealous widget
#

is the space necessary

brisk zenith
#

no

thin trout
#

Yes because of triple quotes?

brisk zenith
#

still no

#

a single """ is still invalid syntax, whether you parse it as triple or not

#

having a pair """""" is valid syntax, whether you parse it as triple or not

#

so ultimately having a space there isn't necessary

thin trout
#

"""" isn't a valid syntax but " " " " is

brisk zenith
#

oh hmm that's true.

#

fair enough then :D

grizzled cloak
#

My favorite even/odd its still & 1

snow beacon
#

I'm partial to a recursive definition, but it's not so esoteric, and works a lot better in Scheme than Python.

grizzled cloak
#

a fun little experiment i did. kinda esoteric because it involves brainfuck.
trans-piling your bf code to python!

gilded orchid
#
def oddeven(i, e=0):
 if i==0:
  return e
 return oddeven(i-1, e^1)

@snow beacon here's my terrible recursive solution

grizzled cloak
#

slightly more readable

marsh void
#
>>> def is_even(x):
...     return not x & 1``` honestly `&1` is the best lol
gilded orchid
#

Can someone explain why these aren't the same?


def oddeven(i, e=0):
 if i==0:return e
 return oddeven(i-1, e^1)

f=lambda i,e=0:[e,f(i-1,e^1)][i>0]
sick hound
#

the second one will always recurse

#

the first one only recurses if i isn't 0

marsh void
#

^

gilded orchid
#

Oh yeah

#

How could I make it so it doesn't always recurse?

sick hound
#

f(i-1,e^1)if i>0else e

gilded orchid
#

Would there be some way to do that with short-circuiting?

sick hound
#

as in and/or stuff?

#
>>> f=lambda i,e=0:i>0and f(i-1,e^1)or e
>>> f(0)
0
>>> f(1)
1
>>> f(2)
1
>>> f(3)
1
>>> f(4)
1
>>> f(5)
1``` if you do it like this it doesn't work properly
gilded orchid
#

yeah, and and or stuff

grave rover
#

why not just f=lambda x:x&1

gilded orchid
#

IFcoltransG brung up the idea of a recursive solution

#

and I wanted to see how short I could make it

formal sandal
#

f=(1).__and__

#

1 character shorter!

edgy kelp
#

f=1 .__and__

lament ibex
#

Nice didn't know about that whitespace hack

marsh void
#

it makes sense actually

proper vault
#
  1. Is a float literal, 1 . is the . operator
formal sandal
#

!e

print(1..imag)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

0.0
marsh void
#

lol

gilded orchid
#
x=quit
y=x.__class__
y.__add__=print
y.__pos__=x
x+x++x+x```
Can someone explain to me how this works? It outputs something but idk how
wind maple
#

heck

proper vault
#

the last +x does nothing

lament ibex
#

x+x => print(quit)
+x => actually quit

wind maple
#

yeah

proper vault
#

other than that, it prints x, then adds +x to that. which is the __pos__ (unary +), which is quit

gilded orchid
#

how is x+x print(quit)?

wind maple
#

x = quit assigns the built-in quit to x
y = x.__class__ therefore becomes an instance of Quitter (due to the implementation)
Let's now skip and examine the line
x + x + +x +x which gets evaluated to x.__add__(x).__add__(x.__pos__()).__add__(x)
Now, we change __add__ on the class to be print, and __pos__ to quit, which makes it do
print(quit); quit()

#

because y.__add__ becomes print

#

and y is the class that x is an instance of

#

and the repr of quit is the message you see when you do quit without the parens

odd blade
#

cool

#

what's x + +x how it that evaluated to __add__(x.__pos__())

wind maple
#

x + (+x) is x.__add(+x) which is x.__add__(x.__pos__())

odd blade
#

ah (+x)

#

ye thanks

gilded orchid
#

Wait does that mean that Python could be TC without any brackets? Since you can basically call any builtin and do control flow with while loops?

wind maple
#

wdym without any brackets

gilded orchid
#

Without using any of ()[]{}

wind maple
#

no

#

only if you count "haha I put the program in an overloaded operator" as turing complete

gilded orchid
#

But like

#

You can do storage with vars

#

You can do control flow with while loops

#

And you can add and subtract from numbers

#

That sounds like it could easily make a 2 counter Minsky machine

#

Which is TC

snow beacon
#

It might be hard if you didn't have the site module.

grizzled cloak
#

@gilded orchid you should try brain fuck!

#

You have to write your own compiler but its pretty simple. Max 5min

#

Its tc but only has 8 operators

snow beacon
#

Brainfuck requires an infinite tape, and lists are hard to make without []. I think a Minsky machine would be easier.

formal sandal
#

!e ```python

This is syntactically correct!

s = "o;(b.b)-=o (a.a)"
compile(s, "", "exec")

night quarryBOT
#

@formal sandal :warning: Your eval job has completed with return code 0.

[No output]
formal sandal
#

poor a.a

#

What is the shortest way to define such o, a, b so that the expression can run?

#

!e

class x:a=b=1
a=b=x
o=abs

o;(b.b)-=o (a.a)
night quarryBOT
#

@formal sandal :warning: Your eval job has completed with return code 0.

[No output]
formal sandal
#

Yay

#

lmao

#

I have a shorter solution

#

!e

a=o=b=exit()
o;(b.b)-=o (a.a)
night quarryBOT
#

@formal sandal :warning: Your eval job has completed with return code 0.

[No output]
gilded orchid
#

It outputs the lyrics to the 12 days of christmas

#

(most of it is autogenerated by a script I wrote but it should be fairly efficient)

#

also yeah, brainfuck is by no means the easiest way to prove something TC

#

2 counter minsky machines and some weird esolangs (like Tip, Three Star Programmer, MINIMAX, or the waterfall model) are a lot better easier to use for proving turing completeness

proper vault
#

Simulate a nand gate which you can nest

#

Though that can be non-trivial depending on context

formal sandal
#

Nesting it might not be enough, it doesn't automatically allow for self-reference

#

Like in a SR NAND latch.

snow beacon
#

There's no implicit iteration in nand gates.

formal sandal
#

!e

from functools import wraps

def inherit_from(parent):
    def decorator(child):
        @wraps(child)
        def func(*args, **kwargs):
            prepared_object = parent(*args, **kwargs)
            child(prepared_object, *args, **kwargs)
            return prepared_object
        return func
    return decorator

def base(*_, **__):
    d = {}
    d["self"] = d
    return d

@inherit_from(base)
def animal(self, size, age, *_, **__):
    self["size"] = size
    self["age"] = age

dog = animal(25, 10)
print(dog)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

{'self': {...}, 'size': 25, 'age': 10}
formal sandal
#

O O P

marsh void
#

LOL

crystal mica
#

@thin trout @lyric fog

#

!e ```py
print(import('functools').reduce(lambda m, x: m * x, [1, 2, 3, 4, 5]))

night quarryBOT
#

@crystal mica :white_check_mark: Your eval job has completed with return code 0.

120
crystal mica
#

Was this what you guys were looking for?

lyric fog
#

i was just joking

crystal mica
#

you got me haha

thin trout
#

Yep that's it

#

Now I'm gonna spend my day understanding what's going on

crystal mica
#

math.prod() looks super clean on 3.8 too, thanks @tame crow for showing me that there's one lol

#

it's functools.reduce()

thin trout
#

Oh that's an handy function!

zealous widget
#
In [11]: np.product(np.array([1,2,3,4,5,6]))
Out[11]: 720
#

๐Ÿ˜ฆ

crystal mica
#

It is very handy

#

Salt, no!

#

built in only!

zealous widget
#

wah

marsh void
#

Actually, reduce was built-in

proper vault
#

(prod:=lambda m,x: m if len(x)==0 else prod(m*x[0],x[1:]))(1,[1,2,3,4,5,6,7])

#

no imports

#

walrus is much nicer than a Y combinator

formal sandal
#

!e

print(
(lambda r,a:r(r,a))(lambda f,x:1if x<2else x*f(f,x-1),5)
)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

120
formal sandal
#

Are classes with inheritance (let's assume multiple inheritance is not allowed) isomorphic to functions with composition?

pine edge
#

wait, walrus operator lets you reference the name you're assigning to?

zealous widget
#

i wouldn't be too surprised if they were isomorphic, but i have no idea how one would construct the isomorphism

#

inheritance seems a lot messier to deal with

#

i suppose just prove it non-constructively by showing they're both turing complete or something

formal sandal
#

Well, you could formalize what a class is...

#

But having dictionaries is kinda cheating.

proper vault
#

thats another way to do it

brazen geyser
#

prod = lambda x, n=1: (all((n := n*i) for i in x), n)[1]

#

how bout this

formal sandal
#

!e

from math import log, exp
print(
exp(sum(map(log, [1, 2, 3, 4, 5])))
)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

119.99999999999997
formal sandal
#

Only works for positive numbers, though.

brazen geyser
#
reduce = lambda x, f, n=1: (all((n := f(i,n)) or True for i in x), n)[1]
lyric fog
#

@formal sandal in function composition you have id function

#

there isnt id class strictly speaking

#

unless we mean function composition in python only, in which case its kinda hard to say

snow beacon
#

You could have a class that inherits but with pass as the body. That'd be an identity.

lyric fog
#

it won't since it'll still be registered as its own class

#

its a class that does nothing yes,

#

for functions it's different since we can re-define function as Input -> Output (relevance to composition) <- i take this back

snow beacon
#

And for classes, parent -> child

#

While the parent and child compare unequal, they have the same behaviour.

lyric fog
#

idk about defining empty class as id

snow beacon
#

Would you like to elaborate? What meaningful change does it cause?

lyric fog
#

it doesn't add anything to the class, sure, but the inheritance exists still
can't replicate the mapping onto itself concept

#

you can say feature-wise, input+function in python and class+inheritance in python would have this isomorphism comparison

#

let me brainstorm a bit

#

ok i can put in better wordings as i'm thinking more about this:

#
  • we're making morphism between: input - class, function - inheritance
  • id function exists, id inheritance doesn't (strictly speaking)
  • you make an empty class (would be equivalence to no input), in order to replicate an inheritance that adds nothing to the class behaviour, but it is still a separate inheritance
#

functions:

def id(x):
  return x

def f(x):
  return str(x)

id o f (x) ~~ id(f(x)) ~~ f(x)
e.g. id o f (1) = id(f(1)) = '1' = f(1)

class:

class Empty:
  pass

class A(Empty): # inheritance is made by python
  pass          # implicitly A -> Empty not A -> A

class B(A): # now we have B -> A -> Empty
  pass

??? what's the equivalence of id composition ???
snow beacon
#

I was imagining the reverse.

class Foo:
    def __new__(x):
        return str(x)

class FooComposedWithIdentity(Foo):
    pass
lyric fog
#

now we're mapping class to function

snow beacon
#

Isn't that what we want to do?

lyric fog
#

see, in your example you have a class that does the equivalence of a function
effectively re-name function to class

#

i'd imagine op's question along the line of,

  • since we can do composition typeA -> typeB -> typeC, which makes a typeA -> typeC function for functions,
  • can we do classA inherits classB inherits class C (which makes classA inherits classC as a result of implicit composition)?
#

to which, would be my answers when i bring out id function
but your example is basically re-aliasing function to class, input -> output becomes argument -> object

#

which are 2 different cases

snow beacon
#

The __new__ function was just an example. The class could instead have, for instance, a property as its data.

lyric fog
#

yeah same point still

snow beacon
#

The point was to demonstrate that you can inherit from it without changing the data.

#

I think the important part is what aspects of functions need to be supported by the morphism to classes.

lyric fog
#

see op question wasn't that clear so idk

#

i might have misunderstood it and they meant your example

snow beacon
#

I can define a set of functions, where each one inputs a class, and returns another class that inherits from the parent, except with some attributes changed.

#

Each of those functions obviously has a direct mapping to a class inheritance.

lyric fog
#

if i take his sentence literally without intepreting,
class maps to function, inheritance between 2 classes map to composition between 2 functions
what would be an example,
for function you have input -> output, what is the equivalence of class, argument -> class instance?

#

or argument -> class behaviours

#

what would a normal inheritance i.e. composition look like

#

@snow beacon

snow beacon
#

If a composition uses a function to transform a python object into a python object, then inheritance uses a class body to turn a class into a class.

#

The equivalence relation between objects couldn't be the same as for classes

lyric fog
#

see we can't even cover the basic before getting to edge case

snow beacon
#

Classes aren't the same python objects as each other, but they can have the same behaviour.

#

What exactly do you mean by 'normal inheritance'?

lyric fog
#

normal -> any

#

like producing a new class with combined behaviours?

#

a function obviously has purpose: transform object to object as you said,
in which case compose becomes clear

i'm trying to find out the equivalence in terms of purpose when you literally make a class

#

so i know what we are composing (when we inherit classes)

snow beacon
#

I would say if their class dicts are the same, they are equivalent.

#

Ignoring anything trivially different like __name__

#
def BaseFunc():
    return 1
def FunctionToCompose(x):
    return x + 1
FunctionToCompose(BaseFunc())

class BaseClass:
    x = 1
class ComposedBaseClass(BaseClass):
    x = BaseClass.x + 1
lyric fog
#

this example is class makes property from argument (or lack of argument?)

snow beacon
#

I don't know what you mean, but this example demonstrates how to compose an incrementation function onto a function that returns a number, and also an incrementation class body onto a base class that stores a number.

lyric fog
#

composition between 2 morphisms, function o function -> new function

def BaseFunc(): # first function
    return 1
def FunctionToCompose(x): # second function
    return x + 1
FunctionToCompose(BaseFunc()) # this is the composition / composed function

equivalence should be inheritance between 2 classes

class BaseClass: # first class
    x = 1
class ComposedBaseClass(BaseClass): # this is already the composed
    x = BaseClass.x + 1
#

see i can't even see this class example as a composition

#

when you compose a function B -> C (input output objects), and a function A -> B, you get a function A -> C

#

now in order to apply to class i need to identify what is my class' equivalence of Input -> Output

#

what am I composing

snow beacon
#

The whole parent class is the input.

#

(That's why BaseClass has no parent; it doesn't take input.)

lyric fog
#

i don't think we're on the same page still

snow beacon
#

Composition is an operation, which takes a mapping of inputs to outputs, i.e. a function, and another function. It applies the mapping of inputs to outputs. Inheritance is an operation, which takes a mapping from base class to new class, i.e. a class body, and another class. It applies that mapping to the other class.

#

There's a modification you need to do to be able to refer to the parent class inside the class body, which is to insert the parent class name at pertinent points. Otherwise, it's the same.

lyric fog
#

which takes a mapping of inputs to outputs, i.e. a function, and another function
which takes a mapping from base class [missing equivalence of inputs -> outputs] to new class,

snow beacon
#

That's just a matter of terminology.

#

In the context of functions, an input is an argument, and output is a return value.

lyric fog
#

no it's a matter of the concept which is fundamental to all this

snow beacon
#

With classes, the input is the base class. The output is the newly define class.

lyric fog
#

now you're confused even the bare definition (before we even get to composition)

def f(x):
  return str(x)
# a number -> a string reprenstation of said number

class A(randomArgs):
  someProp = 1
  def someMethod():
    pass
# no equivalence, there is no base class newly class here
snow beacon
#

randomArgs is the base class, A is the new one.

lyric fog
#

so now classes have to take other class as argument for the analogy to work?

#

what if i take a number

snow beacon
#

So your point of contention is that classes can only transform certain python objects and not others?

lyric fog
#

my point is there isn't an isomorphism from function -> class

#

maybe injective

#

which is required before we start defining composition

snow beacon
#

I think I understand then.

#

Let's take the print function: it prints out its argument and returns None. The result None would need to be encoded into a class, as would the input, so let's say:

class input:
    value = "hello"

class Printer(input):
    print(input.value)
    value = None

I've defined a class that does the same thing as the print function, except input and output are encoded as the .value of various classes.

lyric fog
#

i wouldn't argue against specific classes, since you can always find many types of classes, that you can make a homomorphism from composition -> inheritance

snow beacon
#

I guess I should write a program that transforms any function into a class inheritance then?

lyric fog
#

that means its injective, only specific types of classes

#

anyways

snow beacon
#

I agree there.

#

Or at least, the message I thought I saw for a second.

lyric fog
#

there are a lot of similarities you can draw between these 2
however it won't be isomorphic or homomorphic (include this as well cause i believe its relevant)

#

message i deleted ^

snow beacon
#

I think I was looking for a morphism between some subset of possible classes, and all functions.

lyric fog
#

yeah
i should get back to work tho ๐Ÿ˜ฆ
thanks for the insights, i'm actually not an expert in python in many ways

snow beacon
#

You seem well versed in maths.

calm rampart
#

@lyric fog a class can return any object if you define __new__

class f:
    def __new__(cls, x):
        return str(x)``` also str itself is a class ๐Ÿ˜›
#

a class is just a kind of callable object, just like a function. you could build a parallel class system with another kind of object, though of course the objects would have to be instances of a real class as well (in python 2, such a thing actually exists with the classobj/instance types for old-style classes)

snow beacon
#

It seems like you can make injective mappings either way between classes and functions, but probably not anything bijective.

zealous widget
#

that was my initial thought, but i think just proving both turing complete is good enough

snow beacon
#

Functions are lambda calculus+

#

Classes can contain arbitrary code. Looks like both are TC

grave rover
#

Is it possible to get/change the bytecode of a class before it's created?

thin trout
#

Wdym by before it is created?

grave rover
#

Well

thin trout
#

Like before you create an instance of that class?

grave rover
#

Before the class is created

#

Lemme give an example

#
@modify(b"d\x00", b"d\x01")
class x:
    a = 1
    b = 2

print(x.a)  # -> 2
thin trout
#

Decorators are executed after class creation ๐Ÿ™ƒ

#

Your example will be expanded by the interpreter to

class x:
    a = 1
    b = 2

x = modify(x, b"d\x00", b"d\x01")

print(x.a)  ```
#

But this decorator can be easily created i think

brazen geyser
#

maybe using a metaclass

grave rover
#

Metaclass also doesn't have access to it

steep mauve
#

lol

#

you can easily manuplate bytecode with metaclasses

grave rover
#

how so

#

you'd call type.__new__(...) or similar

steep mauve
#

actually class body is a function

grave rover
#

not a function

#

a code object

#

but inaccessible at the metaclass level iirc

#

metaclass only gets the evaluated params: (classname, baseclasses, dict)

marsh void
#

Btw is there gc.get_objects() thing for other implementations of Python?
Really wondering about this now lol

grizzled cloak
#

@marsh void does that just return all objects in the python instance?

marsh void
#

Yeah

grizzled cloak
#

there has to be. or does pycharm somehow hook into every objects creation?

marsh void
#

idk

#

I mean get_objects returns completely everything GC'ed

grizzled cloak
#

hmm

#

dir() will return everything in scope

#

in IPython:

%whos
Variable   Type      Data/Info
------------------------------
A          type      <class '__main__.A'>
a          A         <__main__.A object at 0x000001C042A90DA0>
sys        module    <module 'sys' (built-in)>```
#

vars() will print a lot more

marsh void
#

Yeah I need some more Python's installed lol

#

@grizzled cloak I need to get object.__dict__ of type dict, thatโ€™s why I am asking lol

#

len(gc.get_objects())
6557

steep mauve
#

martmists, yes it is a function object

#

not a code object

sick hound
#

Yea they are functions

#

i dont know what you are looking for

#

but this can alter class code by their metaclasses

marsh void
#

praise the ฮป

snow beacon
#

That's pretty neat.

marsh void
#

I am lazy to write an actual calculator parser so lol

thin trout
#

@marsh void if I understand correctly you abort the operation if any function call aren't in the env right?

zealous widget
#

i think i made one for codewars

marsh void
#

@thin trout well, I am just restricting the eval, exec and breakpoint, and env is just for additional stuff

#

Yeah I am overriding exit but print isnโ€™t required to override though

thin trout
#

Oh yeah if there is an INVALID_CODE

zealous widget
#
class Calculator:
    """
    Given the problem statement included parentheses in its list of operators, this version can parse them.
    
    It will also take care of un-spaced input, so `.evaluate("(5*(3+2))/4")` is valid.
    """
    def evaluate(self, my_string):
        if isinstance(my_string, str):
            my_string = "".join(i if i.isdigit() or i == "." else f' {i} '
                                for i in my_string).split()
            my_string = [i if i in "()+-*/" else float(i) for i in my_string]

        def check_for(operators, my_string):
            op_dict = {"+":lambda x, y:x + y,
                       "-":lambda x, y:x - y,
                       "*":lambda x, y:x * y,
                       "/":lambda x, y:x / y}

            while any(op in my_string for op in operators):
                for i, op in enumerate(my_string):
                    if str(op) in operators:
                        my_string[i - 1:i + 2] = [op_dict[op](my_string[i - 1],
                                                              my_string[i + 1])]
                        break
            return my_string

        def find_matching_parens(my_string):
            scope = start = 0
            for i, symbol in enumerate(my_string):
                if symbol == "(":
                    if not scope:
                        start = i
                    scope += 1
                elif symbol == ")":
                    scope -= 1
                    if not scope:
                        return start, i

        while "(" in my_string:
            start, end = find_matching_parens(my_string)
            my_string[start: end + 1] = [self.evaluate(my_string[start + 1:end])]
        return check_for("+-", check_for("*/", my_string))[0]

my code was lengthy because i implemented parenthesis

thin trout
#

You couldn't have used regex?

snow beacon
#

I made something similar with a lalr parser library.