#esoteric-python

1 messages · Page 71 of 1

brisk zenith
#

nop

wind maple
#

rip

brisk zenith
#

maybe ```py
valid_python_version = (
match (amount=3)
[3, 7, :].or [3, 5, :] (True)
[:, :, :] (False)
)

would be good syntax for that
#

actually no, or is a keyword

#

darn

#

the | operator wouldn't work because that would become invalid syntax too

#

and also precedence would be a fuck too

sick hound
#

.either

sonic ginkgo
#

@wind maple my fork lets you put a callable in there

#

(which obviously isnt the same)

#

is there a way to override what isinstance does?

#

like if i implement a class, can i also define how isinstance checks work? or is that baked into the runtime

hot crypt
#

type(inst) == type(NewClass())?

#

ah override nvm

wind maple
#

metaclass with __instancecheck__

sonic ginkgo
#

beautiful

#

elegance inbound

#

"elegance"

wind maple
#

CPython impl detail AFAIK

sonic ginkgo
#

😦

wind maple
#

er I'm thinking of __subclasses__

#

no idea about the status of subclasscheck

sonic ginkgo
#

looks like its part of the spec

#

pep 3119

#

alternatively (or additionally) you could implement fall-through of patterns

#
valid_python_version = (
    match (amount=3)
        .either[3, 7, :][3, 5, :] (True)
        [:, :, :]                 (False)
)
#
import math

from match import match
from match.pattern import Not, __recall__
from whatever import _

log_safe = (
    match (amount=1)
       [Not[float]] (float, __recall__)
       [_ <= 0]     (math.nan)
       [:]          (math.log)
)

🤷

#
import math

from match import match
from match.pattern import Not, __recall__, raises
from whatever import _

log_safe = (
    match (amount=2)
       [Not[float], :] (float, __recall__)
       [_ <= 0, False] (math.nan)
       [_ <= 0, True]  (raises(ValueError, "Must be a positive real number"))
       [: ,:]          (math.log)
)
#
from math import log

def log_safe(x, err=False):
    if not isinstance(x, float):
        return log_safe(float(x, err=err))

    if x <= 0:
        if err:
            raise ValueError("Must be a positive real number")
        return math.nan

    return math.log(x)
#

you could probably develop some kind of compiler that optimized away redundant operations, for when the stuff inside the match [] is expensive

sick hound
#

or you can add new syntaxes anytime you want

#

with hooking to tokenizer

#

*cpython only

marsh void
#

What’s match?

near igloo
#

How would I run minecraft from command line?

marsh void
#

Lmao what

brisk zenith
#

i've made a small change to allow for multiple patterns, but i'm not sure which format i prefer visually: ```py
valid_python_version = (
match (amount=3)
[3, 7, :] [2, 7, 16]
(True)

    [:, :, :]
        (False)

)

valid_python_version = (
match (amount=3)
[3, 7, :] [2, 7, 16] (True)
[:, :, :] (False)
)

valid_python_version = (
match (amount=3)
[3, 7, :]
[2, 7, 16] (True)

    [:, :, :] (False)

)

they all work syntactically though
#

i think i like the second one the most

rugged sparrow
#

yea the second one looks good

sonic ginkgo
#

@brisk zenith i like the 3rd

calm rampart
#
class AutoSuperInitMeta(type):
    def __new__(cls, name, bases, dic):
        self = type.__new__(cls, name, bases, dic)
        if '__init__' in dic:
            self.__init__ = cls.wrap_init(self.__init__, self)
    def wrap_init(init, cls):
        code = init.__code__
        argcount = code.co_argcount+code.co_kwonlyargcount
        argnames = code.co_varnames[:argcount]
        def wrapper(self, **kwargs):
            mykwargs = {}
            for name in argnames:
                if name in kwargs:
                    mykwargs[name] = kwargs.pop(name)
            super(cls, self).__init__(**kwargs)
            init(self, **mykwargs)
        return wrapper
sonic ginkgo
#

whats foo?

calm rampart
#

oh, sorry

#

foo was a temp function i used in the repl to remind myself how code objects worked

sonic ginkgo
#

!e

class HasSuperInit(type):
    def __init__(cls, name, bases, dct):
        def superinit(self, *args, **kwargs):
            super(cls, self).__init__(*args, **kwargs)
        cls.superinit = superinit

class A:
    def __init__(self):
        self.x = 1

class B(A, metaclass=HasSuperInit):
    pass

b = B()
print(b.x)
night quarryBOT
#

@sonic ginkgo Your eval job has completed.

1
sonic ginkgo
#

wait hold on

#

how did that work, i forgot to call init

#
class HasSuperInit(type):
    def __init__(cls, name, bases, dct):
        def superinit(self, *args, **kwargs):
            super(cls, self).__init__(*args, **kwargs)
        cls.superinit = superinit

class A:
    def __init__(self):
        self.x = 1

class B(A, metaclass=HasSuperInit):
    def __init__(self):
        self.superinit()

b = B()
print(b.x)
#

thats what i meant to write

#

how did that first one even work o_O

calm rampart
#

if you don't define init the parent init is called first anyway

sonic ginkgo
#

ah

#

(TIL)

#

!e

class HasSuperInit(type):
    def __init__(cls, name, bases, dct):
        def superinit(self, *args, **kwargs):
            super(cls, self).__init__(*args, **kwargs)
        cls.superinit = superinit

class A:
    def __init__(self):
        self.x = 1

class B(A, metaclass=HasSuperInit):
    def __init__(self):
        self.superinit()

b = B()
print(b.x)
night quarryBOT
#

@sonic ginkgo Your eval job has completed.

1
calm rampart
#

how do you tell if a function has *args/**kwargs?

sonic ginkgo
#

in this case, i dont

calm rampart
#

no i'm asking for my thing

sonic ginkgo
#

youd have to do what you did hacking around w/ inspect.signature

calm rampart
#

though I think it doesn't matter because they appear after all explicit arguments (even keyword-only) in varnames

#

yeah i'm trying to figure out how you do it without inspect

#

probably in co_flags

#

yep, 4 and 8 respectively

sonic ginkgo
#
import inspect

def f(x, *args, y=1, **kwargs):
    return

inspect.signature(f).parameters['args'].kind.name == 'VAR_POSITIONAL'
calm rampart
#

varnames is, empirically, all positional args, then all kw-only args, then *args, then **kwargs

#

(and then locals, obviously)

#

well, probably cells then locals

sonic ginkgo
#

why in the world does a ParameterKind have a .numerator and .denominator attribute

calm rampart
#

because it's a number

sonic ginkgo
#

ah

calm rampart
#

for some reason ints have them

#

which means bool and every enum has them

sonic ginkgo
#

oh its an enum

calm rampart
#

even though floats don't

sonic ginkgo
#

thats cause ints are a subset of rationals

#

rational meaning "can be represented as a ratio of integers"

calm rampart
#

so are most floats

sonic ginkgo
#

"most" GWlulurdWaitWhat

calm rampart
#

infinity nan

sonic ginkgo
#

only countably

#

whereas you have an uncountably infinite number of irrationals between every rational

calm rampart
#

yeah but you can't represent an irrational number in a float

sonic ginkgo
#

true, floats are basically giant integers

#

but logically theyre supposed to behave more like a real

calm rampart
#

i'm just surprised they don't have the properties anyway

#

and throw exceptions on inf/nan

sonic ginkgo
#

im glad they dont. they shouldnt

calm rampart
#

it has as_integer_ratio()

sonic ginkgo
#

what does?

calm rampart
#

float

#
>>> .3.as_integer_ratio()
(5404319552844595, 18014398509481984)```
sick hound
#

@sonic ginkgo wow cool)

class HasSuperInit(type):
    def __init__(cls, name, bases, dct):
        def superinit(self, *args, **kwargs):
            super(cls, self).__init__(*args, **kwargs)
        cls.superinit = superinit

class A:
    def __init__(self):
        self.x = 1

class B(A, metaclass=HasSuperInit):
    def __init__(self):
        self.superinit()

b = B()
print(b.x)

Is this for init only?
If so, how to make it work for any method?

calm rampart
#

in most cases you don't always want to call the original method at all

sonic ginkgo
#

oh weird @calm rampart, why do floats have that but ints dont?

calm rampart
#

and there's no way to automatically determine whether it's wanted or not

sonic ginkgo
#

@sick hound no you can't make it automatically detect and call the parent method without a lot more work

#

again, i recommend none of this

#

you will come back to this code in 6 months and not have any idea what's going on

sick hound
#

can a method pass or receive arguments implicitly (except for self)?

brisk zenith
#

well, what value might it take? why can't it use a variable from an outer scope?

sick hound
#

@brisk zenith is this the only easily implemented option in python (use a variable from an outer scope)?

brisk zenith
#

i mean, as far as i can tell, yes. i don't see how it might be useful to be implicitly passed though

sick hound
#

@brisk zenith

class A:
    def __init__(self, **kwargs):
        self.a = 1

class B(A):
    def __init__(self, **kwargs):
        self.super(**kwargs)
        # ideally i want:
        #self.super()

    def super(self, **kwargs):
        # I need to get here
        # 1) method from which self.super called
        # 2) kwargs
        # that is in this case:
        super().__init__(**kwargs)
        # but in general case I need:
        #super().method_I_called_from(method_I_called_from_args)

b_inst = B()

print (b_inst.a)
calm rampart
#

what exactly do you mean by implicitly passed?

#

arguments can have default values

#

oh you're still on the super thing?

sick hound
#

))

calm rampart
#

anyway I think the thing you're proposing is not likely to be as useful as you think it is

#

in many cases you will want the derived method to accept different arguments from the parent class's method, especially for init

#

I think you could do it with frame inspection - that's how super() itself finds the self argument

sick hound
#

@calm rampart Well this is not an advertisement, but I really want to spend a lot of time working with the kivy framework.
If you look at the source code, then almost everywhere the same _init__: it takes **kwargs and uses super.
https://github.com/kivy/kivy/search?q=__init__&unscoped_q=__init__

roughly the same thing is happening in the code of my applications..
and instead of reading the code, I read super.
In addition, I often make a mistake when I copy-paste some old method when creating a new method (if it has a lot in common) but forget to change the super (method name or arguments).
I would just like to try to radically solve this issue.

maybe now I’ve even convinced you a little)

calm rampart
#

maybe but how many methods other than __init__ do that

sick hound
#

@calm rampart many methods. e.g. on_touch_down, on_touch_move, on_touch_up. And this is only standard ones, besides this, there are many other cases.

tepid pulsar
#

you could make a decorator and a metaclass/another decorator for the class (you'll need both or you'd have to go with descriptors) that does the calling of super for you (with a bit of magic help from the inspect module for getting which arguments to extract and so on) not that I recommend sth like this...

Ideally you would extend your linter to issue warnings for wrong method calls with super. but its not the way super was meant to be used, its intentionally left to the programmer to choose the method to call, more power, more responsiblity XD. they could have literally made the parser recognize unmatched method calls or even just add the appropriate method call just like how super() (with no args) works, but they didn't. you better not fight the language.

tepid pulsar
#

(didn't notice ppl already suggested that above)

zealous widget
#

TIL you can give functions attributes:

>>> x = lambda: None
>>> x.test = "Hello, world!"
>>> x.test
'Hello, world!'
calm rampart
#

it only works for functions written in python though

#

you can't attach attributes to functions that are from C modules

zealous widget
#

what's the explanation of that behavior

#

i was looking up empty classes and came across a bunch of useful stuff i didn't know about, like simple name spaces

calm rampart
#

BuiltinFunctionType objects don't have a dict

zealous widget
#

fair

grave rover
#

still tryina figure out how to apply a decorator to every function that gets defined :(

vocal oyster
#

a metaclass?

grave rover
#

but you cant patch all functions easily

#

how would you even get into it

snow beacon
#

The metaclass is passed the class dict, so you can map that dict onto a new one with decorated functions using any number of techniques and feed it into type

#

Unless you mean every function in the whole program.

#

Maybe you could do that with sys.settrace monitoring globals()

#

Or, the simpler option: do the globals() check once, after you've declared all your functions.

tepid pulsar
#

[mem for _, mem in inspect.getmembers(MyClass) if inspect.isfunction(mem)] should give you all the user-defined functions @grave rover then all you need is to define a decorator for the class you want all its methods

#

or use inspect.isfunction in a metaclass with the dict passed in. you don't want to also decorate superclasses methods.

sick hound
#

how can I add code to the end of a method using ast?

snow beacon
#

You can't just use a decorator?

sick hound
#

@snow beacon I need to add super to the end of each method.
in order to experiment
Before

class A:
    def a(self, **kwargs):
        pass

After

class A:
    def a(self, **kwargs):
        pass
        super().a(**kwargs)

brazen geyser
#
from functools import wraps

class A:
    def a(self, **kwargs):
        pass

a = A()

@wraps(a.a)
def patched_a(self: A, **kwargs):
    self.a(**kwargs)
    super().a(**kwargs)

a.a = patched_a
#

would something like this suffice?

#

that super call might need a little tweaking though

#

not sure how it'll operate in this context

#

or does it specifically have to be via AST?

grave rover
#

@tepid pulsar that doesn't make it so if I import a library all of its functions will be patched tho

#

I mean like ```py
register_global_func_wrapper(some_func)

def abc(...):
...

abc is now wrapped with some_func```

distant wave
#

Define "all of the functions"

#

Every single function defined anywhere, or top level functions, or?

grave rover
#

Any (non-anonymous) function defined anywhere

distant wave
#

You can do it with ast.parse, catching "FunctionDef", although I've never used it before

grave rover
#

🤔

#

so FunctionDef.apply_wrapper(my_func)?

sick hound
#

@brazen geyser Is it possible to make it work with every method (that not startswith __), for example using metaclass?

sick hound
#

@brazen geyser should your code work?

from functools import wraps

class A:
    def a(self, **kwargs):
        pass

a = A()

@wraps(a.a)
def patched_a(self: A, **kwargs):
    self.a(**kwargs)
    super().a(**kwargs)

a.a = patched_a
a.a()
Traceback (most recent call last):
  File "main.py", line 15, in <module>
    a.a()
TypeError: patched_a() missing 1 required positional argument: 'self'
#

also I don't get what does

self: A, **kwargs```
mean
rugged sparrow
#

@sick hound self: A is type hinting

#

**kwargs allows for passing keyword args

brazen geyser
#

my bad, i didnt test the code

#

you gotta use MethodType to create a new method

#

so like this

from types import MethodType
from functools import wraps


class A:
    def test(self, **kwargs):
        print('A test', kwargs)


class B(A):
    def test(self, **kwargs):
        print('B test', kwargs)


old_test = B.test

@wraps(B.test)
def new_test(self: B, **kwargs):
    old_test(self, **kwargs)
    super(B, self).test(**kwargs)

b = B()
b.test = MethodType(new_test, b)
b.test()
#

you could also replace B.test directly

#

like this:

B.test = new_test
b = B()
b.test()
#

as for Is it possible to make it work with every method (that not startswith __), for example using metaclass?

#

yea probably

#

you can use inspect.getmembers(B, inspect.isfunction) to get a list of all of B's user defined methods

#

along with their names

#

then you can use setattr(B, function_name, new_function) to replace it

#

at least thats how i think it might go

sick hound
#

thanks I'll try this way)

sick hound
#

@brazen geyser I am confused here

from types import MethodType
from functools import wraps

class MyMeta(type):

    def __init__(cls, name, bases, dct):
        super().__init__(name, bases, dct)

        methods =  cls.get_object_methods(cls)
        for method_name in methods:
            method = getattr(cls, method_name)

            old_test = method

            @wraps(method)
            def new_test(self: cls, **kwargs):
                old_test(self, **kwargs)
                super(cls, self).test(**kwargs)

            method = MethodType(new_test, cls)

            setattr(cls, method_name, method)



    def get_object_methods(cls, object):
        object_methods = [method_name for method_name in dir(object)
                  if callable(getattr(object, method_name)) and not(method_name.startswith('__') and method_name.endswith('__'))]

        return object_methods



class A:
    def test(self, **kwargs):
        print('A test', kwargs)


class B(A, metaclass=MyMeta):
    def test(self, **kwargs):
        print('B test', kwargs)


b_inst = B()
b_inst.test()

B test {}
Traceback (most recent call last):
  File "main.py", line 46, in <module>
    b_inst.test()
  File "main.py", line 18, in new_test
    super(cls, self).test(**kwargs)
TypeError: test() missing 1 required positional argument: 'self'
brazen geyser
#

you dont need to use MethodType when replacing the class attributes

#

only for replacing bound methods on already existing instances

#

so setattr(cls, method_name, new_test)

#

im also not sure why def get_object_methods(cls, object): has the object param at all, since it's a duplicate of cls

sick hound
#

oh really it works now? wow

#

@brazen geyser but if I have another method not named test how to write this line in that case? python super(cls, self).test(**kwargs)

#

I need something like that.

brazen geyser
#
            @wraps(method)
            def new_test(self: cls, **kwargs):
                old_test(self, **kwargs)
                super(cls, self).getattr(method_name)(**kwargs)
#

youll also probably have to spawn this off into another function altogether to keep method_name inside a local scope so it doesnt change

#
class MyMeta(type):
    # ...
    def new_method(cls, method_name, old_method):
        @wraps(old_method)
        def result(self, **kwargs):
            old_method(self, **kwargs)
            #super(cls, self).getattr(method_name)(**kwargs)
            getattr(super(cls, self), method_name)(**kwargs)
        return result
sick hound
#

super(cls, self).getattr(method_name)(**kwargs)
Is this right
AttributeError: 'super' object has no attribute 'getattr'

brazen geyser
#

derp, __getattr__

#

or, getattr(super(cls,self), method_name)

#

ah, you cant even call __getattr__ from the outside with the dunders

#

so yeah, getattr(super(cls,self), method_name)

sick hound
#
from types import MethodType
from functools import wraps

class MyMeta(type):

    def __init__(cls, name, bases, dct):
        super().__init__(name, bases, dct)

        methods =  cls.get_object_methods()
        for method_name in methods:
            print (method_name)
            method = getattr(cls, method_name)

            old_test = method

            @wraps(method)
            def new_test(self: cls, **kwargs):
                old_test(self, **kwargs)
                getattr(super(cls,self), method_name)(**kwargs)
            setattr(cls, method_name, new_test)



    def get_object_methods(cls):
        object_methods = [method_name for method_name in dir(cls)
                  if callable(getattr(cls, method_name)) and not(method_name.startswith('__') and method_name.endswith('__'))]

        return object_methods



class A:
    def test(self, **kwargs):
        print('A test', kwargs)

    def test1(self, **kwargs):
        print('A test1', kwargs)


#class B(A): # without metaclass
class B(A, metaclass=MyMeta):
    def test(self, **kwargs):
        print('B test', kwargs)

    def test1(self, **kwargs):
        print('B test1', kwargs)


b_inst = B()
b_inst.test()


#

well .. seems to work)

brazen geyser
#

there's also this

>>> class A:
    def test(self):
        pass

    
>>> class B(A):
    pass

>>> getattr(B.__mro__[1], 'test')
<function A.test at 0x0000027D19A35D38>
>>> 
#

so you can store a reference to the super function beforehand

#

therefore without needing to even call super() each time

sick hound
#

@brazen geyser thanks a lot! I really didn’t know many things, to be honest I still do not fully understand everything that is happening here) I think I need to take a few hours to comprehend all this.

so even if I don’t need these tricks with the “super”, then in any case, this is a very useful experience.

brazen geyser
#

no worries

marsh void
#

I bet me2beats is Russian 🤔

sick hound
#

@marsh void yep, did you understand this because of my bad english?:)

marsh void
#

@sick hound no, because we, Russians, tend to write hello) and stuff

#

And your English is good, but let’s not continue since it is esoteric-python

rugged sparrow
#

@brisk zenith want to try and make that actually work? ^

brisk zenith
#

hm?

#

in what way?

rugged sparrow
#

Like make it actually print unbelievable

#

Without changing the comparisons

#
if 1 == 1:
    if 1 != 1:
        print("unbelievable")
``` so basically make this actually print
#

Ctypes should make it do-able right?

brisk zenith
#

yeah i reckon it'll be quite easy

rugged sparrow
#

Wait actually

#

Could probably use tokenize

brisk zenith
#

how?

rugged sparrow
#

same way its done here, but we replace the existing token

#

maybe

#

actually i dont think that works

rugged sparrow
#

class myInt(int):
  def __eq__(self,*args): return True
  def __ne__(self,*args):return True

myInt.__hash__ = int.__hash__

from ctypes import *

py_object.from_address(id(1)+sizeof(c_size_t)).value = myInt

if 1 == 1:
    if 1 != 1:
        print('unbelievable')
        

#

@brisk zenith ctypes worked tho

brisk zenith
#

yup, i was thinking of doing the same sort of thing :D

#

except on a lower-level

#

i was gonna modify the tp_richcompare c function pointer in the PyLongObject type struct to make ints always return True on all comparisons

crystal mica
#

that is pure evil

#

love it

rugged sparrow
#

Ah that would be cool

brisk zenith
#

i managed to get it work using my cpystructs helper module but i couldn't figure it out without it for some reason

#

i'm rewriting that module anyways

rugged sparrow
#

Noice that module is really cool

brisk zenith
#

it was never completed and the code wasn't great, but it most definitely helped a lot with this sort of hackery even in its early stages haha

rugged sparrow
#

true that lmao

#

heh after running that code int(1) causes a segfault

brisk zenith
#

it's a bit much when i'm importing a private class from _ctypes

rugged sparrow
#

yeah a bit lmao

rugged sparrow
#

@sick hound the hash thing is because for some reason myInt would occasionally not inherit it from int ```py
Python 3.6.8 (default, Jan 14 2019, 11:02:34)
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.

class myInt(int):
... def eq(self,*args):return True
... def ne(self,*args):return True
...
myInt.hash

#

this could cause segfaults and/or TypeError

rugged sparrow
#

@brisk zenith i have a challenge for you. idk if its possible but hey why not. implement an operator in python like ++

#

without modifying the interpreter

calm rampart
#

what determines whether __builtins__ is a dict or module at module start?

rugged sparrow
#

@calm rampart wdym?

calm rampart
#

like, ```
C:\Users\Random>echo print(type(builtins)) > foo.py

C:\Users\Random>py -m foo
<class 'module'>

C:\Users\Random>py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

import foo
<class 'dict'>

#

it seems like it's a module in the main script (same result for py foo.py) and a dict in imported modules

rugged sparrow
#

It may replace it's module with it's dict using globals

calm rampart
#

apparently not... anyway, the module loader is presumably written in C and has access to references to both the module and the dict, it's just unusual it makes one choice for main script and the other choices for imported modules

rugged sparrow
#

Yeah that is a bit weird

calm rampart
#

which object is interp->builtins

#

ok it's the dict

#

ok, here is where it sets it for the main module

#

and here, i think, is where it's set for imported modules

#

weird

rugged sparrow
#

No kidding

gilded orchid
#

What are some cool uses for the assignment expressions that are coming in python 3.8?

thin tusk
brazen geyser
#

reading stuff in chunks

with open(path) as file:
    while chunk := file.read(1024):
        #...
thin tusk
#

@brazen geyser that one is nice

zealous widget
#

make some list comprehensions nicer, e.g.

my_list = [a:= A.T**-1 for A in some_matrices if a == 1 or a == -1]

so i don't have to compute that hard thing to compute an infinite number of times

nocturne saddle
#

Your code won't run, though, since the conditions at the end get evaluated before the item portion at the start of the list comprehension

#
my_list = [a for A in some_matrices if (a := A.T**-1) == 1 or a == -1]
#

That will, but I'm not sure if it's more readable than an explicit multiline for-loop to avoid the costs

#

Guess I just need to get used to it

zealous widget
#

i really hate a whole line for assignment when the variable is a one-off

nocturne saddle
#

It depends on the context. I'd say I prefer adding a line if it aids readability over one-liners that take a couple of seconds to decipher in a real project

#

Lines don't really cost me anything, but having to figure out what a complicated one-liner does when I read code takes me time

#

That said, I am a fan of list comprehensions in general

pure dew
#

i have written somn particularly foul one-liners in my time

#

For example, here's one for an old challenge we did here:

line_gen = (lambda t, r: map(lambda line: chr(32).join(line), list((lambda tran, text:(lambda derot:(lambda lines:list([(yield (lambda words:r.sample(list(map(lambda word: word.strip(derot[63] + derot[855]), words)), len(words)))(line.split())) for line in lines[1:]]))(derot.splitlines()))(text.translate(tran)))(str.maketrans(t.d), t.s))[1:]))(__import__("this"), __import__("random"))
rugged sparrow
#
(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])([[0]*a 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 None for 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])([[[0]*a for x in range(a)] for x in range(2)]))))((lambda i:i if i > 2 and i < 12 else exit())(int(input('Board Size (max 9): '))+2)))))((lambda x,y,p=(lambda x:[print(' ',*range(1,len(x[0])-1),sep=' '),[[[print(r,end='') if c == 0 else [print(' ',end=''),print(['■','F'][x[0][r][c]], end='') if x[0][r][c] != 2 else 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] == 1 and y[1][r][c] == '*') for c in range(len(y[0][r]))] for r in range(len(y[0]))],q][-1].count(True) == [[[w.append(y[1][r][c] == '*') for c in range(len(y[1][r]))] for r in range(len(y[1]))],w][-1].count(True))(y) else print('You Flagged All The Bombs!')])) ``` @pure dew 
How's this one?
#

Guess what it does lmao

tropic gulch
#

summon the devil

rugged sparrow
#

Run it. But be warned it only works on Unix based systems

pure dew
#

looks like a minesweeper game

torn moth
#

Isn't that just minesweeper mate

rugged sparrow
#

Yeah it is

torn moth
#

Sadly discord makes the text so messy

#

:/

rugged sparrow
#

@torn moth that’s one line of code lol

pure dew
#

I'm impressed

#

how long did that take?

rugged sparrow
#

Like a 3 days

hot crypt
#

minesweeper?

rugged sparrow
#

Cause I have a strategy for onelining. Some of my more exotic oneliners took way longer

hot crypt
#

wait i was scrolled up

brisk zenith
#

i also have a strategy for one-lining @rugged sparrow :D

rugged sparrow
#

list comps ftw

rugged sparrow
#

'''
tryExceptRet(t,a,f,e)

t=try func, can have args
a=tuple of args for try lambda #not passed to except lambda
f=except func #can have up to three args, which will be the Exception Class, Exception Instance, and Traceback
e=tuple of Exception types to check for
#all args optional except try func
'''

tryExceptRet = lambda t,a=(),f=lambda:None, e=(Exception,),r=[]:(lambda q=type('',(*filter(lambda x:'tDe'in x.__name__,object.__subclasses__()),),{'__enter__':lambda s:0,'__exit__':lambda s,*a,c=f.__code__:[r.append(f(*a if c.co_flags == 71 else a[0:c.co_nlocals]))] if issubclass((a[0] or object),e) else 0})()(t)(*a):q if q != None else r.pop() if r else None)()``` @pure dew
pure dew
#

noice

rugged sparrow
#

its oneline try except

#

it means you can catch exceptions in a lambda

brisk zenith
#

i don't like that so much because you're modifying the bytecode, and so it's difficult to actually say it's "one line" when it's also some other bits of code

rugged sparrow
#

While it's true there are other lines through the ContextDecorator, where am I modifying bytecode? Or is that also in the ContextDecorator @brisk zenith ?

brisk zenith
#

is it not that bit with the f.__code__ stuff?

rugged sparrow
#

Nah that's to make the except lambda work with *args or arg1,arg2 #no arg 3

#

It lets me get the number of args and the co_flags

distant wave
#
$ python -m timeit -s "import random" "round(random.random())"
1000000 loops, best of 5: 235 nsec per loop
$ python -m timeit -s "import random" "random.choice([0, 1])"
200000 loops, best of 5: 982 nsec per loop
$ python -m timeit -s "import random" "random.choice([True, False])"
200000 loops, best of 5: 999 nsec per loop
$ python -m timeit -s "import random" "[True, False][round(random.random())]"
1000000 loops, best of 5: 333 nsec per loop
zealous widget
#

wtf why is random() faster than choice on a tiny list

distant wave
#
$ python -m timeit -s "import random" "[True, False][int(random.random() * len([True, False]))]"
500000 loops, best of 5: 437 nsec per loop
#

I don't know, but from experience I know it's the case

zealous widget
#

is random written in c?

#

and choice isn't?

distant wave
#

choice is not

#

neither is randbelow

zealous widget
#

and round is faster than int?

#

oh, its just the int code needs a few extra steps

distant wave
#
$ python -m timeit -s "import random" "int(random.random())"
1000000 loops, best of 5: 213 nsec per loop
$ python -m timeit -s "import random" "round(random.random())"
1000000 loops, best of 5: 238 nsec per loop
#

int is a little faster but can't be overoptimized for the two choice case

#

needs an addition/multiplication, which takes longer than round()

zealous widget
#

so round(random.random()) is the best coin flipper?

distant wave
#

And yes, random.random() is C, but choice is not

#

As far as I can tell

#

Oh this is a great comment from the c source

#

note that

  • 9007199254740992 == 2**53; I assume they're spelling "/2**53" as
  • multiply-by-reciprocal in the (likely vain) hope that the compiler will
    optimize the division away at compile-time
zealous widget
#

i wonder if numpy.choice is faster

crystal mica
#

in the (likely vain) hope

#

lol

distant wave
#

lets find out..

#
$ python -m timeit -s "import numpy" "numpy.random.choice(1)"
50000 loops, best of 5: 8.48 usec per loop
zealous widget
#

christ numpy

distant wave
#
$ python -m timeit -s "import numpy" "numpy.random.choice([False, True])"
20000 loops, best of 5: 9.93 usec per loop
crystal mica
#

numpy OP

zealous widget
#

no its slow

#

micro seconds > nano seconds

#

i blame the import

distant wave
#
$ python -m timeit -s "import numpy; a = numpy.array([True, False])" "numpy.random.choice(1, size=1000)"
10000 loops, best of 5: 27.6 usec per loop
#

Numpy's optimized for chunk-getting random it seems

#

cause that's 27.6ns per choice there

crystal mica
#

o i read it wrong

zealous widget
#

can you time just the parts after the import

#
>>> import numpy as np
>>> import timeit
>>> timeit.timeit("np.choice(np.array([True, False]))", number=10000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/timeit.py", line 237, in timeit
    return Timer(stmt, setup, timer).timeit(number)
  File "/usr/lib/python2.7/timeit.py", line 202, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 6, in inner
NameError: global name 'np' is not defined
#

oh, am i in the wrong python

#

i still have the same error in 3.6

distant wave
#

odd

zealous widget
#

lemme try with setup

#

this works:

>>> timeit.timeit("np.random.choice(np.array([True, False]))", setup="import numpy as np", number=10000)

also it was np.random.choice and not np.choice

gilded orchid
#

Is there a shorter way to do this?

from random import*
random.randint(0,1)
#

I tried using id() and os.urandom, but I couldn't get either of them to be shorter

zealous widget
#

shortest as in least amount of code? because Bast seemed to find the fastest was round(random.random())

gilded orchid
#

Least amount of code (including imports), not fastest

zealous widget
#

if you did a starred import can't you just refer to the function as randint(0,1)

#
>>> from random import*
>>> randint(0,1)
1
>>> randint(0,1)
0
gilded orchid
#

Oh yeah, oops

#

But is there a way to do it without using random, cos that's a lot of bytes in a code golf

tropic night
#

how many times do you call the function?

#
>>> from random import randint as r
>>> r(0,1)
1
>>> 
#

a bit longer import string.. not sure it would be worth it in your case

snow beacon
#

(8&id([[]]))>>3

#

Seems to change each time

#

Actually, if you don't mind a boolean, delete the second >

#

And the brackets.

zealous widget
#

whats id() do

snow beacon
#

Generally it's the id in memory, at least in CPython

crystal mica
#
Return the identity of an object.

This is guaranteed to be unique among simultaneously existing objects. (CPython uses the object's memory address.)```
zealous widget
#

oh nice

#

well it be sufficiently random for regular ol' python

crystal mica
#

specially nice to tell people why == and is are totally different

#

also that's a smart way to use it

snow beacon
#

So 8&id([[]])>3 makes a new list object, takes the third bit, and checks if it's 8 or 0

#

Third most significant bit, that is

zealous widget
#

can you use an empty list, or does it have to be a list with an empty list

snow beacon
#

Empty list is interned

#

Which means they don't create new objects each time.

#

At least, it seems that way in the interpreter.

zealous widget
#

how about 0-tuples

snow beacon
#

Nah, that's immutable, it probably just interns all the short ones

zealous widget
#

seems to be constant

#

weird, id({1}) jumps between two values for me

#

id([1]) seems kinda random

snow beacon
#

-10 changes

#

So does 257

crystal mica
#

id(()) is consistent for me

#

so it's probably interned

snow beacon
#

I think all empty sequences are.

wind maple
#

id changes between runtimes

#

unless you explicitly disable it

snow beacon
#

Yes, but if you use it more than once in the same program

crystal mica
#
for _ in range(100):
    print(id([[]]))```
#
2329381786184
2329381786696
2329381786184
2329381786696
2329381786184
2329381786696
2329381786184
2329381786696```
wind maple
#

though some objects have constant IDs

snow beacon
#

-10 is shorter

crystal mica
#

Why it's jumping back and forth? lol

wind maple
#

that's probably just

#

memory allocation and deallocation

crystal mica
#

oooooooh

snow beacon
#

It's pseudorandom

tropic night
#

cant you just use list() instead?

#

or would it be the same?

zealous widget
crystal mica
#

lol list() is an interesting one

#

at first it seems random

#

but later on it's the same behaviour as [[]]

#

alloc then delloc

snow beacon
#

set() is shorter

zealous widget
#

[1] shortest i think

snow beacon
#
>>> for _ in range(100):print(id([1]))
...
19745368
19745368
19745368
19745368
19745368
19745368
19745368```hmmm
crystal mica
#

set() and [1] gives fixed value for me

zealous widget
#

i was getting different values

crystal mica
#

only list() gives different results for the first 80 or so times

#

3.7.4

tropic night
#

they are fixed objects.. strange that it reuses the old memory addresses

zealous widget
#
In [79]: id([1])
Out[79]: 139721610400840

In [80]: id([1])
Out[80]: 139721610395400

In [81]: id([1])
Out[81]: 139721610385032

In [82]: id([1])
Out[82]: 139721610400712
#

python 3.6

#

no cython though

tropic night
#

do you have to delete the ref before you make it again?

crystal mica
#
for _ in range(100):
    a = [1]
    print(id(a))
#
2395210797640
2395210798152
2395210797640
2395210798152
2395210797640
2395210798152
2395210797640
2395210798152```
#

lol

zealous widget
#

ha

snow beacon
#

If you were golfing, unless you have a loop, you could just specify a different digit each time you call the function.

crystal mica
#

i feel like im being fooled

distant wave
#

lambda x=[]:8&(id(x), x.append(id(x)))[0]>3

#

untested

tropic night
#

!e

for _ in range(8):
    a = (_,)
    print(id(a))
night quarryBOT
#

@tropic night Your eval job has completed.

001 | 140565156275144
002 | 140565156409472
003 | 140565156275144
004 | 140565156409472
005 | 140565156275144
006 | 140565156409472
007 | 140565156275144
008 | 140565156409472
crystal mica
#

x.append() @distant wave

tropic night
#

!e

for _ in range(8):
    a = (_,)
    print(id(a))
    del(a)
night quarryBOT
#

@tropic night Your eval job has completed.

001 | 140648784765896
002 | 140648784765896
003 | 140648784765896
004 | 140648784765896
005 | 140648784765896
006 | 140648784765896
007 | 140648784765896
008 | 140648784765896
crystal mica
#

rip

tropic night
#

so it reuses the ide when you delete it

snow beacon
#

I think you have to avoid deallocating the old object

tropic night
#

it gets GCed but is not ready for the next iteration, hence the back and forth

snow beacon
#

!e

a = []; for _ in range(10):a+=[a];print(id(a))```
night quarryBOT
#
Certainly not.

Sorry, but you may only use this command within #bot-commands.

crystal mica
#

i cri too

zealous widget
#

a=0, and then a=id(a)

snow beacon
#

Doesn't work for me

zealous widget
#

rip

snow beacon
#

I think a=(a,) works

crystal mica
#

it does work

tropic night
#

that would be the same as adding del(a) would it not?

crystal mica
#
a = []
for _ in range(10):
    a = (a,)
    print(id(a))```
#
2345975470472
2345977149832
2345977112520
2345980053320
2345979993736
2345979993672
2345980053256
2345979993032
2345979993352
2345979993288```
#

lol

snow beacon
#

del a is counterproductive. We want to avoid repeating ids

zealous widget
#
In [111]: a = 0
     ...: for i in range(10):
     ...:     a = id(a)
     ...:     print(a)
10968768
139721610451984
139721610451920
139721610451984
139722060305872
139721610451952
139722060305872
139721610451952
139722060305872
139721610451952
snow beacon
#

We're fighting the garbage collector to get Python to keep allocating memory

zealous widget
#

starts repeating

tropic night
#

yeah, thats what i meant, though not phrased good enough

zealous widget
#

is there some way we can hold a reference to it somewhere

snow beacon
#

The a=(a,) stores the old a

zealous widget
#

oh yeah

snow beacon
#

Inside the new a

tropic night
#

!e

a = []
s = set()
for _ in range(1000000):
    a = (a,)
    s.add(id(a))
print(len(s))
night quarryBOT
#

@tropic night Your eval job has completed.

timed out or memory limit exceeded
tropic night
#

oh..

crystal mica
#

lol

zealous widget
#

that would've been a nice eval

tropic night
#

!e

a = []
s = set()
for _ in range(10000):
    a = (a,)
    s.add(id(a))
print(len(s))
night quarryBOT
#

@tropic night Your eval job has completed.

10000
snow beacon
#

So that works. Now to golf it

tropic night
#

then i take my leave 😄 you guys can golf it away 😄

zealous widget
#

a=[a] is one less byte, does it work as well

crystal mica
#

yep

#

it does

snow beacon
#

Setup code is a=1, then each time you need to do a=[a] and evaluate 8&id(a)>3

#

With Python 3.8 assignment operators you can probably do 8&id(a:=[a])>3

zealous widget
#

i love walrus

snow beacon
#

'walrus'?

zealous widget
#

:=

#

walrus operator

gilded orchid
zealous widget
#

try an extra set of parenthesis around it

snow beacon
#

I think it's the 8& bit

zealous widget
#

hmm, i think the scope of a before the assignment is limited too

crystal mica
#

changed to 8&id(a:=[a])>>3 and it shows 0 or 8

#

but removing the > will always be false

#

lol

zealous widget
#

oh

crystal mica
#

that's better

snow beacon
#

Looks like it stores objects with 64 bits of memory

crystal mica
#

cant wait for this walrus

tropic night
#

then just install 3.8

#

😄

crystal mica
#

I wish

#

I mean I do have it for local testing

#

but to write distributable scripts with it, welp

snow beacon
#

You could package it with the Python version

zealous widget
#
a=[]
for i in range(10):
   a=[a]
   print(id(a)%3%2)
#

mod something not divisible by 2 first, then mod 2

#

that's not uniform though

#
a=1
for i in range(10):
   print(id(a:=[a])%3>0)

is that the same length as the other version

#

saves a byte

#

oh thats not uniform either, hm

snow beacon
#

id is implementation-defined anyway

drowsy cobalt
#
x = ([1, 2], 3)
x[0] += [4, 5]

Vote python if you think this will mutate the list, or vote oof if you think it will error

(try not to run in repl first)

rugged sparrow
#

||```py

x = ([1,2],3)
x[0] += [4,5]
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
x[0]
[1, 2, 4, 5]
x
([1, 2, 4, 5], 3) ```||

#

@drowsy cobalt ???

drowsy cobalt
#

^ spoiler

sick hound
#

||I guess I vote both since it mutates the list and errors||

wind maple
#

The reason it happens is
||First the value of x[0] (so in this case the mutable list) is put on the top of the stack
+= is evaluated on the list object successfully, the list is mutated
The result of the previous operation is assigned to x[0], this fails as tuples are immutable

FWIW I've never ever seen this in real code. Moral of the story is tuples are immutable but their contents are still just as mutable as they were before||

vocal oyster
#

||```python

a = []
b = (a, "<- mutable?")
b
([], '<- mutable?')
a.append("yes")
b
(['yes'], '<- mutable?')

sick hound
#

could it be convenient to have this syntax?

class A:
    def a(x, y = x):
        print (y)

A().a(1)
#--->
#1

(not sure if I choose the right channel)

pure dew
#

i cant see that being remotely useful

#

enough to warrant the effort to add it

calm rampart
#

eh i can see some situations, especially if it can be any expression involving previous arguments

#

but it's at odds with the whole way python default arguments work

sick hound
#

the usual solution is

    def a(x, y = None):
        if y is None:
            y = x

but it is not so readable imo

pure dew
#

the only times i've had to do that, I've had enough of them to make it worthwhile to use kwargs

brazen geyser
#

hmm

#

could be hackable with settrace maybe?

#

or a decorator would do too

crystal mica
#

interesting @drowsy cobalt if i do += it will raise error but assign anyway

#

.append() will just append and mutate the list inside tuple

sick hound
#

@brazen geyser
don’t see a way how to do this with decorator, could you just give a hint?

brazen geyser
#

well, it would be super jank

#

and youd need some way to specify y=x using a special value

#

maybe a class

#

then inside the decorator, you return a wrapper that checks the args/kwargs for values of this type and replace them

#

and use inspect to figure out the values associated with positional args

#

iirc there's getargspec as one option

#

overall your signatures would look something like this:

@magic_decorator_goes_here
def test(x, y=PreviousArgument('x')):
    pass
#

or maybe OtherArgument since order wont matter as youll have all the values at once anyway

#

very much not worth the effort/overhead

#

but could be a fun exercise

sick hound
#

@brazen geyser thanks. yea, I'll think if I need to do it at all

jade dust
#

I put in checks to simplify the actual algorithm, meaning you can't have Args that point to other Args

#

Also, there's a bug in inspect.BoundArguments where it doesn't keep keep track of which argument were originally args or kwargs

#

So this will probably fail on functions with *args or **kwargs in their signature

brazen geyser
#

noice

sick hound
#

@jade dust omg, cool! thanks for sharing)

jade dust
#

Wow, thanks!

#

@brazen geyser did all the work though, lol

sick hound
#

constants doesn't exists in python?

grave rover
#

Opinions on elvis operator and deratives and if they belong in python?

#

i.e. ?:, ?., ? :, etc

formal sandal
#

!e ```python
my_list = []
print(my_list or "hello_world")

my_list = [1, 2, 3]
print(my_list or "hello_world")

night quarryBOT
#

@formal sandal Your eval job has completed.

001 | hello_world
002 | [1, 2, 3]
sonic ginkgo
zealous widget
#

i always liked how lisp looked, but not as much as i like how python looks

sonic ginkgo
#

"por que no los dos"

#

python with syntactic macros? hell yeah

marsh void
#

This hylang looks quite terrifying

sick hound
#
print (not not None is None)```
#

didn't know that)

sick hound
#

that's parsed as not not (None is None)

#

and None is None, so not not True is not False is True

sick hound
#

ah, got it)

tepid pulsar
#

or operates in a different way than would an elvis operator if it existed, elvis operator is all about "None-awareness", or null-safety. imo the only use case that I find it really useful is for default args, instead of doing val if val is not None else some_default you'd do val ?? some_default. I don't know how I feel about it really kinda excited kinda don't see much use for it in a dynamic lang, In Kotlin its a highly praised feature, but its also supported by the compiler to provide smart casts and whatsnot, maybe that will be the case for python too because of type hinting support. btw here is the pep for it, its deferred currently https://www.python.org/dev/peps/pep-0505/

#

don't get me wrong I am all in for an elvis operator, just don't see much use for it in my code 🤷 I'd rarely use things like null safe member access.

edgy kelp
#

Not entirely esoteric but I'm wondering how python assigns tuples and people who understand python a bit deeper seem to be around here
Got this test code, but getting various outputs on different interpreters

print((1,) is (1,))
print(([],) is ([],))
a=(1,)
b=(1,)
print(a is b)
sick hound
#

([],) and ([],) will always be different because they create new lists

edgy kelp
#

yeah those two are the only ones I'm sure about

sick hound
#

(1,) and (1,) seem to be separate values in python 2, and constants in python 3, but whether or not they're the same constant depends on the interpreter

#

actually, nevermind, it looks like they're always different?

edgy kelp
#

I get True for the first one and False for the third one

sick hound
#

in python 3.7 they're the same constant

edgy kelp
sick hound
#

for the third one, what happens depends on if you do it all at once or as lines in an interactive interpreter/REPL

#

or at least it does in 3.7

#

before 3.7 they're always different constants anyway

#

in python 3.7, if you do them as separate lines, they get compiled separately and different constants are generated

#

but if you do them in the same line they're the same constant

edgy kelp
#

it looks like it keeps them in some sort of a cache that gets deleted shortly affter or something like that

sick hound
#

not exactly a cache, python code gets compiled into a code object and that code object has a list of constants in it

edgy kelp
#

getting same ids once in a while when I spam id on it, but that could also be just python putting it into the same place

sick hound
#

(1,) is (1,) gets compiled into one code object, and the (1,) only needs to be one constant

#

but if you do it as separate code objects, they have separate lists of constants

#

it's like this example ```py

x = 257; x is 257
True
x is 257
False```

#

if you do 257 twice in the same code object, you get the same 257

#

but if you do it once and then again in another code object, you get a different 257

edgy kelp
#

at least an empty tuple is always the same thing, from what I can see

sick hound
#

makes sense that that would be stored somewhere, like None

#

yep, an empty tuple is always the same thing, which means you can change it into something different and break stuff

#
>>> ()
SystemError: ..\Objects\tupleobject.c:138: bad argument to internal function```
#

well actually now doing anything breaks

#

mutating an empty tuple is a really bad idea

#

it's trying to check the size of an empty tuple

pure dew
#

Hylang is neat, I've played around with it

marsh void
#

Hylang is like python but no

grave rover
#

Not related to python, but... I added decent OOP to Lua ```lua
class "B" {
__ctr = function(self, val)
self.a = val
end
}

class "A" : extends "B" {
__ctr = function(self, val)
super(self):__ctr(val)
end,

help = function(self)
    print(self.a)
end

}

x = A(10)
x:help() -- => 10```

#

apparently function calls are interesting in lua: lua func("abc") func "abc" func [[abc]] -- [[ ... ]] are multiline strings in lua are all the same, similarly: ```lua
func({a: 1})
func {a: 1}

#

then I use the fact that you can add metamethods to objects (called magic functions / operator overloads in python) to make them callable and stuff

#

next update I'm adding to this is a __meta field that defines the metatable it has

crystal mica
#

im tempted to call python / pyd from lua, how possible is that lol

#

I can never get into lua

grave rover
#

They both have a fairly simple interface in C

crystal mica
#

thank you

brazen geyser
#

lua already has provisions for oop

#

tables are basically objects

grave rover
#

yeah but it never had class statements or inheritance or anything

#

thats what I added :D

snow beacon
#

Does Brainfuck have an API for calling Python functions yet?

brazen geyser
#

it does have classes prototypes

grave rover
#

that's the hackiest inheritance I've ever seen and also makes regular instances too bloated

#

though @brazen geyser if you wanna help out with this project, let me know, I can DM the source

brazen geyser
#

it's more or less the same system as js before ES6

#

and afaik the ES6 stuff is basically syntactic sugar anyway

#

sure id be keen to take a look, but im not too keen on working with lua in general 😅

#

for me it's one of those necessary evils for specific circumstances

#

also we're veering off topic lemonpeek

snow beacon
#

Speaking of Lua, does anyone know a way to get Python list indices to start at 1?

distant wave
#

You can make a custom dict subclass that does that for you

snow beacon
#

I mean normal lists themselves. [1,2,3][1] would be 1

grave rover
#

You'd have to patch python

formal sandal
#

!e ```python
class CustomList(list):
def init(self, lst, start=0):
super().init(lst)
self.start = start

def __getitem__(self, index):
    return super().__getitem__(index - self.start)

def __setitem__(self, index, value):
    super().__setitem__(index - self.start, value)

A = CustomList([7, 8, 9, 10, 11], start=1)
print(A[1])
print(A[2])
print(A[3])

night quarryBOT
#

@formal sandal Your eval job has completed.

001 | 7
002 | 8
003 | 9
formal sandal
#

But A[0] will return the last element, which is weird.

edgy kelp
#

well, easy to raise an index error if it's 0

polar plover
#

Well, it's 1 behind the start. So kinda makes sense?

#

@formal sandal

formal sandal
#

If the array starts at 7, it's weird that 6 points to the last element.

grave rover
#

arrays start at 2

zealous widget
#

is that weirder than the array starting at 7?

formal sandal
#

Well, for example, Pascal supports custom array index ranges (b: array [50..100] of Integer;). You might want to reproduce this feature.

edgy kelp
#

if index < self.start: raise IndexError
problem fixed 😛

polar plover
#

What if your want 0 to be a error but not -1? If start is not 0

formal sandal
#

if index in range(0, self.start): raise IndexError(index)

#

if 0 <= index < self.start: raise IndexError(index)

polar plover
#

👍

grave rover
#

try implementing excel's INDEX function

livid sail
#

index to (index-self.start) % self.__len__() for the full periodic boundary condition experience

sick hound
#

what if you made the list indexes start at the end of the list

#

so wat[0] is the last element of wat, and wat[1] is an IndexError

sick hound
#

Haha

#

I saw a meme about the "stat wars array" and implemented it

marsh void
brisk zenith
#

guys, i've done a bad thing.

wind maple
#

what have you done

brisk zenith
#

a function and a class method inside of a function inside of a class method

wind maple
#

doesn't sound too bad

brisk zenith
#
# QuantumGate.pauli_x() right now would give AttributeError

@QuantumGate.register()
def pauli_x():
    return [
        [0, 1],
        [1, 0]
    ]

# but now it doesn't.
x = QuantumGate.pauli_x()

it gives nice results though

#
    @classmethod
    def register(cls, name: str = None):

        if name is not None and not name.isidentifier():
            raise ValueError("Quantum gate name must be a valid identifier")

        def decorator(func):
            nonlocal name

            if name is None:
                name = func.__name__
            
            def wrapper(*args, **kwargs):
                result = func(*args, **kwargs)

                if not isinstance(result, cls):
                    result = cls(result)
                
                return result
            
            @classmethod
            def method(_, *args, **kwargs):
                return wrapper(*args, **kwargs)
            
            setattr(cls, name, wrapper)
            return wrapper
            
        return decorator
#

wait i forgot one thing there we go

#

of course, it'll be used for defining gates dynamically based on the args and stuff.

brisk zenith
#

actually i made it a bit better.

thin trout
#

What's golfing? Real life golfing or python golfing? xd 🤔

polar plover
#

well this is a python server, so I would say: python golfing

tropic gulch
formal sandal
#

Maybe you can make some crazy logic by abusing __bool__...

rugged sparrow
#

@formal sandal you could make it take an iterable instead of two digits to make it more like regular for loops

formal sandal
#

Maybe it's also a good idea to make these loops 'lazy'.

#

So that I can store them and call on demand.

#

Unfortunately, __bool__ must return either True or False, so I have to ditch the fancy return values.

#

Maybe it would make sense to store the last fancy return value.

pure dew
#

you dont even need the lambda in there for that one

formal sandal
#

True.

zealous widget
#

does anyone mind doing some independent timeits for me? trying to see if cv2.filter2D is faster than scipy.ndimage.convolve

sick hound
#

Is it possible to rewrite the add function for numbers?

brisk zenith
#

i believe so, but it would be tricky and very very very unstable

sick hound
#

I don't care I just want the python console to say 1+1
3

brisk zenith
#

oh, well in that case you can overwrite the value of 2 in memory with 3

#

!e ```py
import ctypes
ctypes.memmove(id(3), id(2), int.sizeof(3))
print(1 + 1 == 3)

night quarryBOT
#

@brisk zenith Your eval job has completed.

True
brisk zenith
#

overwriting int.__add__ is significantly more difficult though

whole kiln
#

Hi what is a functions __closure__ attribute for?

sick hound
#

I tried it and it said that the add func is read only

whole kiln
#

I couldn't understand the docs on it

#

Is it related to lambdas somehow?

sick hound
#

Hi Mark!

#

Pls ask that in one of the help channels

rugged sparrow
#
from ctypes import *

class myInt(int):
     def __add__(self,other):
             if self == 1 and other == 1:
                     return 3
             else:return super().__add__(other)

py_object.from_address(id(1)+sizeof(c_size_t)).value = myInt
print(1+1==3)```
#

@sick hound ^ this would work too

#

i think at least

brisk zenith
#

@whole kiln it shows you the variables that a closure can access which aren't in its local scope but aren't in the global scope, i believe: ```py
In [5]: def func(string):
...: def closure():
...: print(string)
...: return closure
...:

In [6]: x = func("hello, world!")

In [7]: x()
hello, world!

In [8]: x.closure
Out[8]: (<cell at 0x7f1d541ac948: str object at 0x7f1d542c4330>,)

In [9]: x.closure[0].cell_contents # this would be the string variable in the func function
Out[9]: 'hello, world!'

whole kiln
#

I thought it was something like that but I tried defining local variables in the parent function and they didn't show up

sick hound
#

it's not just local variables in the parent function, it's variables in the parent function that the function with the closure accesses

brisk zenith
#

ah so it has to actually use them

#

makes sense

#
In [4]: def function(name): 
   ...:     greeting = "hello " 
   ...:     def greet(amount): 
   ...:         for _ in range(amount): 
   ...:             print(greeting + name) 
   ...:     return greet 
   ...:                                                                          

In [5]: f = function("mark")                                                     

In [6]: f(5)                                                                     
hello mark
hello mark
hello mark
hello mark
hello mark

In [7]: f.__closure__                                                            
Out[7]: 
(<cell at 0x7f0abcbfb1f8: str object at 0x7f0abcc696c0>,
 <cell at 0x7f0abcbfbb28: str object at 0x7f0abffe6ab0>)

In [8]: f.__closure__[0].cell_contents                                           
Out[8]: 'hello '

In [9]: f.__closure__[1].cell_contents                                           
Out[9]: 'mark'

In [10]: # notice the `amount` isn't there (obviously, because it changes for each call to the closure)
whole kiln
#

thanks

snow beacon
#

Challenge: write a program that rhymes

#

The more complicated the better.

rugged sparrow
#

@snow beacon like print and int?

#

and by line?

unkempt cloak
#

when i write this code, and python execute it, i'm giggle

__slots__ = ['data'].extend(list(data.keys()))

why that line of code didn't throw any error, and didn't return anything?

sick hound
#

@unkempt cloak because extend call doesnt return the list it self, it mutates an existing list

#

['data', *data.keys()]

#

is what you are looking for i believe

unkempt cloak
#

@sick hound
awesome!!!!

#

thank you!!

sick hound
#

np

snow beacon
#

@rugged sparrow That was what I meant. You don't have to include punctuation or numbers in the rhyme scheme, but ideally every line of code would rhyme with another.

sick hound
#

I love how if yout RT googling for how to replace the string class in python

#

All the search results say you can't

#

Just casual lurking in this chat had like ten different ways of doing it

grave rover
#

still looking for a way to define a global function wrapper that applies itself to every function defined after it

formal sandal
#

@snow beacon

"python"
"cython"
"jython"
#

:)

sick hound
#

is there a way somebody would beable to redefine the keywords like "if" and "pass" ?

#

cuz i want to make a module that just fucks around and destroys python, like redefining false to truent and true to falsnt and messes up calculations

formal sandal
#

Hm.

#

True and False are keywords.

sick hound
#

ik

#

but can i change the keywords?

#

i mean in that specific script, not globally on my pc

formal sandal
#

Well, you could write your own interpreter...

gilded orchid
#
>>> ctypes.memmove(id(True), id(False), int.__sizeof__(True))
    
1555948208
>>> True
    
True
>>> False
    
False
>>> True==False
    
True
>>> 

Why do true and false still show up as true/false despite the fact that I did a memmove?

#

I thought it'd make it so True returned False, but it doesn't?

sick hound
#

oh i just read something about that i think

#

hmm cant find it

#

@sick hound that's in python 2 where True and False are just names

#

@gilded orchid if you check int(True) it's 0, but I guess the stringification of bools is based on their id

#

so if u can swap true and false

#

could u swap while and if

#

no

#

and for and import

#

no

#

darn

#

True and False aren't keywords at all in python 2

#

im talking about python3

#

you can't swap true and false in python 3

#

you can change their values but that's just because they're objects

#

the actual keywords aren't affected

#

what does this code do:

from ctypes import *

class myInt(int):
     def __add__(self,other):
             if self == 1 and other == 1:
                     return 3
             else:return super().__add__(other)

py_object.from_address(id(1)+sizeof(c_size_t)).value = myInt
print(1+1==3)
#

it makes it so that 1+1==3

#

it changes 1 to have a type of myInt

#

but how what gets changed?

#

oh

#
>>> type(1)
<class '__main__.myInt'>```
#

can i do that for all ints at once?

#

instead of doing that in a for loop till forever?

#

well no, only the ints from -5 to 255 (iirc) are cached, so those are the only ones you can change

#

oh

#

but you could change the actual int type with ctypes and that would affect all of them

#

how?

#

I don't know, we're not some kind of cpython structure expert

#

i tried rewriting int.add and it said its read only

#

yes, you can't just assign to it

#

omg

#

i think i got it in vanilla python without ctypes

#

leme type it out

brisk zenith
#

it probably is possible to overwrite the entire int type but i doubt it would be reasonably stable

#

@sick hound that won't work

sick hound
#
class myInt(int):
     def __add__(self,other):
             return self+other+1

int = myIntS
#

it does

brisk zenith
#

it doesn't

sick hound
#

as far as i know

#

that doesn't change actual integers

#

actually it doesn't change anything, it raises a NameError

brisk zenith
#

!e ```py
class myInt(int):
def add(self,other):
return self+other+1

int = myInt
print(type(1))```

night quarryBOT
#

@brisk zenith Your eval job has completed.

<class 'int'>
gilded orchid
#
>>> class myInt(int):
     def __add__(self,other):
             return self+other+1

    
>>> int=myInt
    
>>> 4+5
    
9
>>> myInt(5)+myInt(3)
    
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    myInt(5)+myInt(3)
  File "<pyshell#77>", line 3, in __add__
    return self+other+1
  File "<pyshell#77>", line 3, in __add__
    return self+other+1
  File "<pyshell#77>", line 3, in __add__
    return self+other+1
  [Previous line repeated 990 more times]
RecursionError: maximum recursion depth exceeded
sick hound
#

oh and that

#

🤦

#

why is it still int?

#

why would it not still be int

polar plover
brisk zenith
#

because every integer points to the integer class in memory, they do not point to the int variable

#

unless you overwrite the int class in memory, they will remain unchanged

sick hound
brisk zenith
#

you probably want to take a look at the forbiddenfruit module

sick hound
#

well you changed int into myInt

#

so you're doing myInt.__add__ = myInt.__add__

#

no error

#

and you can't change actual builtin types like that anyway

brisk zenith
#

forbiddenfruit lets you overwrite built-in functions and methods without too much hassle

sick hound
#

ah darn

brisk zenith
#

overwriting int.__add__ in memory is certainly possible with just ctypes though. i'll give it a go in a few minutes.

sick hound
#

why cant i install forbinnenfruit module?

#

probably because you don't have Microsoft Visual C++ 14.0

#

oh i did something

#

python crashed by adding

rugged sparrow
#

@sick hound you just changed the base class of 1 to your __add__ function

#

of course its gonna crash

sick hound
#

ye i noticed

rugged sparrow
#

yea

sick hound
#

its becomming self aware!!

rugged sparrow
#

i assume you used the code to change adding on one that i put up earlier?

sick hound
#

ye

#
from ctypes import *

class myInt(int):
    def __add__(self, other):
        return "meh, i dont really feel like doing calculation right now..."

for i in range(-5, 255):
    py_object.from_address(id(i)+sizeof(c_size_t)).value = myInt
#

without the super

rugged sparrow
#

makes sense

sick hound
#

now what if i want to also make the number 256 do this?

rugged sparrow
#

youd need to overwrite the int class

#

with ctypes

sick hound
#

gosh i need to know how to do that

#

then i can really fuck up python

rugged sparrow
#

just change the base class of () to anything

#

that really fucks it up

sick hound
#

what is ()

rugged sparrow
#

an empty tuple

#

its cached

#

and used in the C code of python

#
Python 3.7.3 (default, Mar 27 2019, 22:11:17) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> py_object.from_address(id(())+sizeof(c_size_t)).value = None
>>> 
SystemError: /tmp/build/80754af9/python_1553721932202/work/Objects/tupleobject.c:141: bad argument to internal function
>>> 1 + 1
SystemError: /tmp/build/80754af9/python_1553721932202/work/Objects/tupleobject.c:141: bad argument to internal function
>>> exit()
SystemError: /tmp/build/80754af9/python_1553721932202/work/Objects/tupleobject.c:141: bad argument to internal function
>>> ```
brisk zenith
#

!e ```py
import ctypes

int.add is defined as a binaryfunc type in C

binaryfunc = ctypes.CFUNCTYPE(
ctypes.py_object, ctypes.py_object, ctypes.py_object
)

this is the pointer to the int's number methods

int_num_ptr = ctypes.c_void_p.from_address(id(int) + 96)

we don't need to add anything to the int's number methods

address because int.add is the first in the struct

int_add_ptr = ctypes.c_void_p.from_address(int_num_ptr.value)

convert the original int.add into a callable function.

this is to prevent recursion errors in the new function

int_add_func = ctypes.cast(int_add_ptr, binaryfunc)

@binaryfunc
def new_int_add(self, other):
return int_add_func(int_add_func(self, other), 1)

convert our new function into a pointer and overwrite the

original int.add pointer with the new one

new_add_ptr = ctypes.cast(new_int_add, ctypes.c_void_p)
int_add_ptr.value = new_add_ptr.value

print(5 + 6)
print(500 + 500)
print(0 + 0)

night quarryBOT
#

@brisk zenith Your eval job has completed.

001 | 11
002 | 1000
003 | 0
brisk zenith
#

huh it didn't work here. must be because the bot is on 3.6 or something

#

@sick hound @sick hound that code there works for python 3.7 and 3.8 though

rugged sparrow
#

cool

#

@brisk zenith how did you find 96?

sick hound
#

didnt work for me

#

and i am on 3.7 i believe

#

im 99% sure

brisk zenith
#

@sick hound maybe. i'll see if i can sort the code out and make it work more

rugged sparrow
#

👌 thanks

sick hound
#

ye im on 3.7.3

brisk zenith
#

oh hmm

#

okay, so it works if you run it in the shell

#

but not in the code

#

i wonder why that may be

rugged sparrow
#

thats weird

brisk zenith
#

oh wait

#

because the values in the code are optimised

#

in the bytecode

#

right, makes sense

sick hound
#

can u fix it?

brisk zenith
#

sort of. the code is still working, but python's bytecode optimiser can't be prevented like that

#

hold on, in the code it causes a segfault now

#

okay yeah i'm not sure how to sort it out for running in the code itself

#

but it works flawlessly in the shell haha

sick hound
#

why would it be different there?

#

is it because there is some time between the commands/

#

?

#

nope its not

brisk zenith
#

i'm not sure why it segfaults in the code.

#

i do have something that works in code though:

#

test = ["this", "is", "a", "list"]
print(test[1])  # outputs 'this'
#

test = "lists start at one".split()
print(test[1:3])  # ['lists', 'start']

works for slices too

sick hound
#

wait what?!

#

how

brisk zenith
#

!e ```py
import ctypes

binaryfunc = ctypes.CFUNCTYPE(ctypes.py_object, ctypes.py_object, ctypes.py_object)

mapping = ctypes.c_void_p.from_address(id(list) + 112)

original_ptr = ctypes.c_void_p.from_address(mapping.value + 8)
original_method = ctypes.cast(original_ptr, binaryfunc)

@binaryfunc
def new_method(self, item):
if isinstance(item, int):
item = item - 1

elif isinstance(item, slice):
    item = slice(
        item.start - 1,
        item.stop - 1,
        item.step
    )

return original_method(self, item)

new_method_ptr = ctypes.cast(new_method, ctypes.c_void_p)
original_ptr.value = new_method_ptr.value

test = "lists start at one".split()
print(test[1])
print(test[2:4])

night quarryBOT
#

@brisk zenith Your eval job has completed.

001 | lists
002 | ['start', 'at']
brisk zenith
#

this one works consistently haha

sick hound
#

from now on arrays start at 1

#

how do we make it start at something else?

brisk zenith
#

change all the - 1s in the function to - whatever

sick hound
#

ye i figgured it out

#

my esoteric module now has a function to chage the array index

brisk zenith
#

how does it work? globals?

sick hound
#

wait what?

#

it doesnt work

brisk zenith
#

i thought it wouldn't

sick hound
#

why??

brisk zenith
#

lemme take a look

#
import ctypes

binaryfunc = ctypes.CFUNCTYPE(ctypes.py_object, ctypes.py_object, ctypes.py_object)

mapping = ctypes.c_void_p.from_address(id(list) + 112)

original_ptr = ctypes.c_void_p.from_address(mapping.value + 8)
original_method = ctypes.cast(original_ptr, binaryfunc)


def change_list_start(index):

    @binaryfunc
    def new_method(self, item):
        if isinstance(item, int):
            item = item - 1

        elif isinstance(item, slice):
            item = slice(
                item.start - 1,
                item.stop - 1,
                item.step
            )
        
        return original_method(self, item)

    new_method_ptr = ctypes.cast(new_method, ctypes.c_void_p)
    original_ptr.value = new_method_ptr.value
#

this works for me

#

wait hold on

#

i forgot to change the index inside

#

give me a moment

#

okay so if you replace those, it works

sick hound
#

got it

brisk zenith
#

you have to change it back to 0 before python closes if you want to avoid segfaults btw

sick hound
#

ah

#

euhm

#

it says my function isnt defined

#
import ctypes

binaryfunc = ctypes.CFUNCTYPE(ctypes.py_object, ctypes.py_object, ctypes.py_object)
mapping = ctypes.c_void_p.from_address(id(list) + 112)
original_ptr = ctypes.c_void_p.from_address(mapping.value + 8)
original_method = ctypes.cast(original_ptr, binaryfunc)

def arraysStartAt(index):
    @binaryfunc
    def new_method(self, item):
        if isinstance(item, int):
            item = item - index
        elif isinstance(item, slice):
            item = slice(item.start - index,item.stop - index,item.step)
        return original_method(self, item)
    new_method_ptr = ctypes.cast(new_method, ctypes.c_void_p)
    original_ptr.value = new_method_ptr.value
brisk zenith
#

is that all of your code?

sick hound
#

yes

#

i import this into console

brisk zenith
#

you have to do module.arraysStartAt(...).. that's how modules work

sick hound
#

oh yea

#

lmao im dumb

#

now, can we swap false and true using ctypes?

#

?

brisk zenith
#

possibly.

#

it's been attempted a bunch of times before, i can't remember if any were successful.

#

(they probably were)

#

i'm not gonna try it right now though, i'm busy at the moment

sick hound
#

sure

#

ima try to rewrite the round function so the numbers are just not rounded

#

so 50.4 --> 50.00000000000000000000000000001

#

this one is just a simple redefinition of the round function

#

lol i found this

#

@snow beacon yes we now can

#
from ctypes import *

binaryfunc = ctypes.CFUNCTYPE(ctypes.py_object, ctypes.py_object, ctypes.py_object)
mapping = ctypes.c_void_p.from_address(id(list) + 112)
original_ptr = ctypes.c_void_p.from_address(mapping.value + 8)
original_method = ctypes.cast(original_ptr, binaryfunc)

def arraysStartAt(index):
    @binaryfunc
    def new_method(self, item):
        if isinstance(item, int):
            item = item - index
        elif isinstance(item, slice):
            item = slice(item.start - index,item.stop - index,item.step)
        return original_method(self, item)
    new_method_ptr = ctypes.cast(new_method, ctypes.c_void_p)
    original_ptr.value = new_method_ptr.value
#

use the arraysStartAt function

#

and make sure to import ctypes

brisk zenith
#

(cough i wrote most of that tyvm lmao)

sick hound
#

lmao

#

i made a option to dissable type conversions

sick hound
#

@sick hound yea you can but that requires defining an encoding because you are going to change the parser

marsh void
#

Lol

sick hound
#

Hi I need to convert a string like this

{'x': 300} + {'x': 0} & {'y': 300} & {'y': 0}

into this (one) object

A (x = 300) + A (x= 0) & A (y= 300) & A (y= 0)

another example

string:

({'x': 300} + {'x': 0} & {'y': 300}) + {'y': 0}

object:

SomeObject == (A (x = 300) + A (x = 0) & A (y = 300)) + A (y = 0)```

And I need to get (return) this new object
How to do this?

I know these dict keys are always strings;
and values are numbers or strings

Is it reasonable to implement this with ast.parse or something like that?


I just started to delve into ast, but it looks like I need a plan of key actions (if using ast is 
suitable in this case).
polar plover
#

@sick hound so basically every dict becomes: A(key=value)

brisk zenith
#

but yes, i imagine ast.parse would be reasonable.

sick hound
#

@polar plover
yes (if I understand you correctly). but there can be several such pairs in the dictionary {'x': 300, 'y': 0} etc
@brisk zenith oh
I thought questions on ast is better to ask here, am I wrong

brisk zenith
#

well, ast is a perfectly normal module to use in python, nothing funky about it really.

polar plover
#

I think it could be done using str.replace

#

it was a string right?

sick hound
#

@polar plover yes

polar plover
#

@sick hound #help-kiwi looks free, we can move there if you want.

night quarryBOT
#
Nah.

Sorry, but you may only use this command within #bot-commands.

crystal mica
#

@grave rover that just occurred to me, idk if you've done it before but I wonder if you can modify object so class Abc: which inherits from it, will have new stuff in it? WHen I tried to modify it directly I got a TypeError: can't set attributes of built-in/extension type 'object'

rugged sparrow
#

@crystal mica what are you trying to edit?

crystal mica
#

object

#

you know howpy class Abc: pass then Abc is automatically inherited from object class?

rugged sparrow
#

yea

crystal mica
#

it's equivalent to py class Abc(object): pass

#

I want to, say, do this before I define Abc

#
object.yes = lambda: print("Yes")```
#

so I can dopy abc = Abc() abc.yes()

rugged sparrow
#

one sec

#

i wanna try something that might work

#

so i managed to add object.yes

#

but it isnt inheriting

#

ah

#

cause everything actually inherits from type

#

not object

crystal mica
#

yeah, I just realized that

#

I substitute builtins.object and rip

rugged sparrow
#

oh i modded it in memory

crystal mica
rugged sparrow
#
Python 3.7.3 (default, Mar 27 2019, 22:11:17) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class myType:pass
... 
>>> myType.yes = lambda *s:print('yes')
>>> myType.__call__ = type.__call__
>>> from ctypes import *
>>> py_object.from_address(id(type)+sizeof(c_size_t)).value = myType
>>> class foo:pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__call__' for 'type' objects doesn't apply to 'myType' object
>>> ``` and replacing type doesnt work right
crystal mica
#

it didnt work for me either

rugged sparrow
#

i have an idea

#

welp that didnt work

crystal mica
#

this is so weird

#

I have to actually call class Abc(type): for it to work

#

what the hell is creating it

#

Hmm, i have an idea

rugged sparrow
#

wait whats working now?

crystal mica
#
import builtins


class MyType:
    pass


MyType.yes = lambda *s: print('Yes')
builtins.type = MyType


class Abc(type):
    pass


abc = Abc()
abc.yes()
#

But this is the same as just extending

rugged sparrow
#

ah i know why that broke it

crystal mica
#

lemme try replacing type.__new__

#

it's a metaclass isnt it

rugged sparrow
#
import builtins


class MyType(type):
    pass


MyType.yes = lambda *s: print('Yes')
builtins.type = MyType


class Abc:
    pass


abc = Abc()
abc.yes()```
#

this might work

crystal mica
#
Traceback (most recent call last):
  File "e:\Projects\hi3-beta-bot\snippets.py", line 17, in <module>
    abc.yes()
AttributeError: 'Abc' object has no attribute 'yes'```
#

I tried that before I had to put type into Abc

#

Weird i know

rugged sparrow
#

ah ik why

#

cause your just redefining the visible type var. while class declarations are getting it from mem

grave rover
#

@crystal mica have you tried our Lord and Savior gyukutai forbiddenfruit?

crystal mica
#

I did

#

I want to avoid it

grave rover
#

o

crystal mica
#

More like see if I can do without it

grave rover
#

But tldr you want to add to object right

#

Doubt it's possible due to impl

crystal mica
#

Yeah, so if I class Abc: it'll have it

#

That's what I doubt haha

brisk zenith
#

i reckon it might be possible.

#

tricky, but possible

grave rover
#

Pretty sure you can't

#

Not in CPython at least

brisk zenith
#

doesn't stop me from trying

#

not yet though, i'm busy

crystal mica
#

I think due to implementation, the original type got loaded into memory

grave rover
#

Oh also here's a fun thing to try:
Dereference None

crystal mica
#

so subclassing it wont take effect unless I specify it to inherit from type again, after subclassed

#

without specifying inheritance, it'll just inherit from the original that's in the memory

#

which explains

#

But then how did forbiddenfruit do it lol

#

modifying the memory directly?

brisk zenith
#

yes

crystal mica
grave rover
#

That's how forbiddenfruit practically works, yeah

brisk zenith
#

i've got until my friend replies to a message to piss about with this idea

#

so, let's see then

#

!e ```py
import ctypes

obj_dict = ctypes.py_object.from_address(id(object.dict) + 16).value
obj_dict["hello"] = 123

class Test:
pass

x = Test()
print(x.hello)

night quarryBOT
#

@brisk zenith Your eval job has completed.

123
brisk zenith
#

@crystal mica @grave rover

#

just modify the mappingproxy's internal dict, easy

#

anyways gotta go bye

crystal mica
#

That is so cheating

#

But I like it

brisk zenith
#

practicality beats purity

crystal mica
#

Thank you @brisk zenith it made me curious for the past 2 hours lol

brisk zenith
#

👌

crystal mica
#

I didnt think of modifying only the __dict__

grave rover
#

oh wow I never would have thought of mappingproxy

#

why the +16 btw?

brisk zenith
#

PyObject_HEAD is 2 pointers

#

so 16 bytes on 64 bit

#

so just skip those 16 bytes to reach the actual dict itself

#

(because mappingproxy itself doesn't allow for assignment)

#

anyways yes bye

sick hound
#

"cause everything actually inherits from type
not object" that's... false

#
>>> ''.__call__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__call__'
>>> type.__call__
<slot wrapper '__call__' of 'type' objects>
>>> isinstance('', type)
False
>>> isinstance('', object)
True```
rugged sparrow
#

@sick hound yah that was cause of a typo by me ```py

''.class
<class 'str'>
''.class.class
<class 'type'>
''.class.base
<class 'object'>

I only checked __class__ not __base__

wind maple
#

not everything inherits from type, but type will always be in the type hierarchy

#

Because type is the type of object

#

and well, really every class

#
class Foo:
    ...
```is really just cool syntax for
```py
Foo = type(
    'Foo',
    (object,),
    {...}
)```
marsh void
#

Haha, I see ctypes is really what's used a lot here

wind maple
#

it's easier to abuse a language when you don't conform to spec and abuse the implementation

marsh void
#

Yep 👍

brisk zenith
#
@define_method(str)
def to_spongebob(self):
    methods = [str.lower, str.upper]
    new_string = ""

    for index, char in enumerate(self):
        new_string += methods[index % 2](char)

    return new_string


print("arrays start at one".to_spongebob())
# outputs "aRrAyS StArT At oNe"

i extended the object attr overwriting to make it nicer :D

#

doesn't work for magic methods because i cba with those yet. but maybe soon lmao

#

at least, not for builtin types

polar plover
#

probably because they are read only.

brisk zenith
#

that's not the problem

#

it's that the magic methods of the builtin types aren't stored in __dict__ like regular attributes and methods

#

instead, they're defined in special C structs

#

and while it is very possible to overwrite that behaviour (i did it yesterday)

#

it can be quite tedious

polar plover
#

oh, ignore me then

brisk zenith
#

haha it's no problem.

#

but usually if something in python is "read-only", it is simply "read-only until import ctypes" 😉

gentle pagoda
#

bf interpreter in 188 chars 😃 any way i can improve it? py t=d=0;p,m="",[0]*1000 for i in input():j="]+[-><.,".find(i);p+=" "*t+"0 m[d]+=1 while+m[d]: m[d]-=1 d+=1 d-=1 print(end=chr(m[d])) m[d]=ord(input())".split()[j]+"\n";t-=(j<3)*(1-j) exec(p)

sick hound
#

Not use exec :P

#

Or semicolons