#internals-and-peps

1 messages · Page 45 of 1

grave jolt
#

A.__str__ is object.__str__?

whole glacier
#

I see, that makes sense, so first it checks the current class __mro__

#

It doesnt have one, so __repr__ is called

spice pecan
#

yeah, exactly

flat gazelle
#

the __str__ of object checks for __repr__ afaik

whole glacier
#

Well

grave jolt
#

that would make sense

whole glacier
#

!e ```py
def str(obj):
return getattr(obj, 'str', obj.repr)()

class A:
def str(self):
return 'hi'

print(str(A()))

fallen slateBOT
#

@whole glacier :white_check_mark: Your eval job has completed with return code 0.

hi
whole glacier
#

In this case it does pick up the __str__

#

So I'm leaning toward the mro

grave jolt
#

We have to find the default __str__ implementation in the C source somehow

flat gazelle
#
In [43]: class K:
    ...:     def __repr__(self):
    ...:         return 'AAAA'
    ...:

In [44]: object.__str__(K())
Out[44]: 'AAAA'
whole glacier
#

Interesting lol

grave jolt
#

so convenient to have cpython cloned, so I don't have to use github's search tool

#

.

#

ooh sorry

#

Yes, hastebin. That's totally python source...

flat gazelle
#

pydis paste always uses .py

#

hastebin sometimes mistakes py for ruby

north root
grave jolt
#
    if (Py_TYPE(v)->tp_str == NULL)
        return PyObject_Repr(v);
#

actually, it highlights it correctly

#

oh, it doesn't

#

it stopped highlighting it correctly when I reloaded it lol

#

so, if it fails to find the object's __str__, it just calls __repr__.

#

And in the __repr__ source:

    if (Py_TYPE(v)->tp_repr == NULL)
        return PyUnicode_FromFormat("<%s object at %p>",
                                    Py_TYPE(v)->tp_name, v);
#

"hey, let's just print the pointer, it's so convenient"

spice pecan
#

I never thought much about the fallback to __repr__, or rather how it's treated in derived classes

grave jolt
#

I'd never though I would understand any of the cpython source

#

But it's written so well

undone hare
#

It is actually pretty decent yeah

grave jolt
#

who needs version control, you can just comment out some code

#

Oh, it's just an explanation

#

I didn't see that it was in Python, lol

spice pecan
#

I really like that actually

#

Explaining Python's C sources with Python code

grave jolt
#

That's an example of a big project made without having a 10-layer class hierarchy.

#

creating a BaseX class for the only purpose of X inheriting from it, which only exists so that AX and BX inherit from it, while only differing in one class attribute

flat gazelle
#

that is java style, and there is a reason java code is written this way. In python it is a lot more questionable though.

grave jolt
#

yes, I felt I was reading Java

spice pecan
#

It would be less questionable if it at least implemented the basic logic that was repeated in every child

snow olive
#

hey guys is there anyone familiar with kivy? I'm in need of some help

flat gazelle
grave jolt
snow olive
#

got it! thank you!

atomic scarab
#

Boys, is it possible to write an programm that will execute a command (pressing left click) when it hears a specific sound? I'm new into phyton

flat gazelle
#

recognising sounds is quite difficult, but it possible in theory

grave jolt
#

but it's probably one of those problems that sounds really easy, but is really hard to implement

#

The code I linked is a part of an API wrapper for VK (the biggest social network in ex-USSR countries). It is not nearly as rich as the Discord API wrapper, and it is already ~22000 SLOC, while discord.py is 12000 SLOC or something.

#

So that java style inflates the code size as well.

#

At least in Python

somber halo
#

that's an audio processing topic @atomic scarab, a more adequate channel for you problem might be #data-science-and-ml

#

I'm back with more quirky stuff from that string interning issue in Python's REPL

#
>>> a = "a b"
>>> b = "a b"
>>> c = "a b"
>>> a is b
False
>>> a is c
False
>>> b is c
False
>>> a = "ab" 
>>> b = "ab"
>>> c = "ab"
>>> a is b
True
>>> a is c
True
>>> b is c
True
>>> a = "a?b"
>>> b = "a?b"
>>> c = "a?b"
>>> a is b
False
>>> a is c
False
>>> c is b
False
>>> a = "a-b"
>>> b = "a-b"
>>> c = "a-b"
>>> a is b
False
>>> a is c
False
>>> c is b
False
>>> a = "a\nb"
>>> b = "a\nb"
>>> c = "a\nb"
>>> a is b
False
>>> a is c
False
>>> b is c
False
#

(sorry for the wall of text)

#

it seems to me that the decision rule is the exclusive presence of alphanumeric characters in string in order for it to be interned.

peak spoke
#

I'm going to guess it's (ascii) valid identifiers below a certain len

somber halo
worldly hedge
#

Can anyone give me a good explanation for the differences of a Semaphore and a Mutex

radiant fulcrum
worldly hedge
#

@radiant fulcrum oof thanks

#

I was wondering on what the real differences are 😛

oblique crystal
#

ooph.... I don't know if this really fits the topic but here it goes: if, say I want to migrate code from CPython 3.5 to 3.7 (or better yet 3.8) is there is a chance that something will break? (assuming that I can install all same versions of the pypi packages that were used in the app)

#

as far as I saw till know usually code from newer Cpython might not run (or work as expected) on prior versions, but it seemed to me that the code from older (like 3.5) would run exactly the same way on new Cpython like 3.7/8

flat gazelle
#

look at the changelogs and see if something got removed. As long as the code does mostly lawful python, it should be fine

oblique crystal
#

well thing is the big parts of code weren't written by me

mellow widget
#

can you update the version and build your app and run all tests against it?

oblique crystal
#

and some part of app I've never even touched/seen 🙂

flat gazelle
#

I would suggest looking at changelogs and seeing what behaviour changed

oblique crystal
#

run all tests
yeah, tests.... not yet there. But the part I've been working with runs on py37

peak spoke
#

there were very few breaking changes to the base language itself

#

for modules etc. you need to check yourself what has changed

wide shuttle
#

There are some major changes to asyncio and some deprecations in that area

#

Although 3.5 already introduced async def/await

#

Still, that part of the library is very much being actively developed

#

Subtle things, like CancelledError no longer inheriting from Exception, but rather BaseException now

oblique crystal
#

yeah quick glances told me that it seems like I would likely to be in trouble if it was 3.4 or older.
Asyncio is one reasons I would like an update: i.e. there is a small part of app I am writing where I want to use aiohttp and local asyncio.run. But the code itself did not use async in past.

mellow widget
#

Best to read through the changelog, and check for any obvious changes which could cause errors, should be able to search your project for changes like Ves said above

oblique crystal
#

also as far as I see in many cases when things are meant to be deprecated they first introduce only a deprecation warning

#

which would persist over several versions

#

before it is fully depcreated

#

I think even if there are some incompatible things they are likely easily fixe-able so I guess I will make a case for upgrading from 3.5 -> 3.8 to my collegues

spiral willow
#

LossBerg, yall containerize?

mellow widget
#

yeah if you're using docker to build your app and run your tests against you could just upgrade your python image version

#

and test it locally

spiral willow
#

yep

#

simple edit

#

FROM python:3.5-slim to FROM python:3.8-slim

oblique crystal
#

I don't think that app has any automated tests as of now

#

about containerization, I should ask

spiral willow
#

great way to test upgrades

oblique crystal
#

locally I only used venv but in production I believe it is docerized

mellow widget
#

if you have a dockerfile or docker-compose.yml then you can build locally

snow kindle
#

I struggle with decorator:

from libs.JsonManager import JsonManager


class ServerData(JsonManager):

    def __int__(self, ServerId):
        super().__init__('./storage/ServerData.json')
        self._Server_Id = str(ServerId)

    '''
    
    decorator
    
    '''

    def conditional_decorator(cls, condition):
        def decorator(func):
            if not condition:
                # Return the function unchanged, not decorated.
                return func
            return cls(func)

        return decorator

    '''
    
    Server Data
    
    '''

    def ServerInitialization(self):
        return True

    '''
    
    User Data
    
    '''

    @conditional_decorator(condition=True)
    def UserMaster(self, user_id):
        try:
            user_id = int(user_id)
        except ValueError:
            raise Exception('Please chose a valid int')
        if str(user_id) in [k for k in self.json_manager["user"]]:
            return self.json_manager["user"][user_id]
        else:
            new = self.json_manager
            new["user"][user_id] = {
                "is_kick": False,
                "is_ban": False,
                "is_mute": False,
                "is_admin": False,
                "reason": None,
                "time": None
            }
            self.json_manager = new
            return self.json_manager

How I can get is right ? (if a great people can correct it fast it will be the best)

mellow widget
#

you don't understand decorators?

snow kindle
#

I want to learns them

mellow widget
#

think of your decorator like this

snow kindle
#

I just want this right for get a correction and see where is my error

mellow widget
#

conditional_decorator(condition=True, UserMaster(self, user_id))

#

UserMaster will execute first and return a value(hopefully), then your decorator will pass the returned value into it

snow kindle
#

No it still wrong

#

can I dm you for send you all the code (in edition) in link ?

mellow widget
#

I'm just about to go offline, but take a read of that. Hopefully that will help u understand decorators and how to use them. If you're still confused ask someone in the chat 👍 good luck

snow kindle
#

some one else ?

hollow crane
#

what's the issue

snow kindle
#

I don't undestand decorator I want some one make my code working for see my error

hollow crane
#

session expired

snow kindle
#

@hollow crane again ? (you can abuse mentioning me because I do it mechanically when I begin to be angry)

hollow crane
#

what's the error then

shy vine
hollow crane
#

oh yeah

snow kindle
#

I know this

#

I want knowleadge

shy vine
#

"I want someone to make my code work" is seeking help.

lost nexus
#

will IOR overwrite keys or append a duplicate?

for example

d = {'one': '1', 'two': '2'}

d |= {'one': '700'}

# desired result is {'one': '700', 'two': '2'}
shy vine
#

Overwrite

lost nexus
#

alright

golden imp
#

oh sweet got renamed

rich wharf
#

python used to have argument unpacking

#
def f(x, (y, z)): pass```
#

but they removed it

languid dagger
#

How long ago was that?

rich wharf
#

The pep was March 2007

languid dagger
#

Huh 3.0 so you can still do it in Python 2

tawdry gulch
#

Whattttt, thats so cool

#

It's not useful, but its cool

#

well, imo not very useful

grave jolt
#

It's kinda useful in lark-parser because it may pass a nested list/tuple tree transformer sometimes

rich wharf
#

I'm working on an iterable class

#

It can map, slice, filter, reduce, sum, and exhaust iterables.

#

It has four states

snow olive
#

if there is anyone familiar with kivy could someone help me out in #help-lollipop ;-; thank you!

rich wharf
#

@snow olive This isn't the right channel for that

snow olive
#

got it ty

rich wharf
#

Iterable Wrapper
States
lazy Lazily generates values from mapping/filtering/slicing
exhaust Generally lazy, but iterates over the iterable to find a match when needed
generate Generally lazy, but iterates over the iterable to find a match when needed, and stores previously exhausted values
sequence Converts the iterable to a list and stores it internally to manage operations
Methods
map Returns a mapped iterable from a function returning the replacement for the previous value
filter Returns a filtered iterable from a function returning a boolean for keeping or removing the value
reduce Takes two values of the iterable, applies a function to them, and repeats with the new value and the next value of the iterable
sum Gets the sum of the iterable
product Gets the product of the iterable
reverse Returns a reversed version of the iterable
list Converts the iterable to a list
len(iterable) Gets the length of the iterable
value in iterable Checks if the iterable contains a value
iterable[index] Gets the value at the index of the iterable
iterable[start:stop:step] Returns a sliced version of the iterable

def gen():
  c = 0
  while True:
    c += 1
seq = iterable(gen())
for i in seq[3::5]:
  print(i)
rich wharf
#

I added a couple new functions

#

tuple, dict, and set return the iterable as a tuple, dict, or set

#

apply takes in a lambda of (keep, value) with keep being a condition of if to keep the value or not and value being the new value, returning a new iterable. It's essentially a merger of filter and map

#

chain allows you to chain one or more iterables to this one

#

+ allows you to add another iterable to this one

#

repeat and * allow you to repeat this iterable a certain amount of times

#

chunks allows you to split your iterable into chunks depending on the size, which works with or without the iterable's length, and optionally allows you to get the remainder piece

#

you can also use / on an iterable to divide it into chunks

cloud crypt
#

I wrote kind of the same thing but it was an Iterator

rich wharf
#

interesting

#

I do see a difference though

#

Mine takes in a state on what type of iterator while yours doesn't

#

But they are quite similar

#

Oh, the difference between yours and mine is that yours clones itself

#

While mine doesn't use cloning and uses other ways to maintain state

#

Anyways I'm going to sleep now, gn

dire hull
#

how advanced do i need to be to use this channel

#

im scared my pleb questions gonna get me banned

gray mirage
#

It's not a help channel, more a discussion channel

wide shuttle
#

Yeah, it's not a help channel; it's in the discussion category

#

It's meant for discussion of the topics mentioned in the channel topic:

#

Discussion on the use cases, implementation and future of the Python programming language including PEPs, advanced language concepts, new releases, the standard library, and the overall design of the language.

flat gazelle
#

well, some questions do fit, but more open ended ones, like What decides whether a string gets interned

dire hull
#

wait this is the old python language lel i lost my brain

#

intimidated by the new name lol i see

blazing lotus
#

is there an alternative to cx_Oracle package?

deft pagoda
#

the idea i had to reduce decorator boiler plate has already been born out by several modules after i searched --- the wrapt module in particular seems pretty sweet here as it preserves function signatures

#

i'm surprised i hadn't heard of it before --- functools.wraps is all i've ever seen

undone hare
wide shuttle
#

I've never looked at the internals of virtual environments before

unkempt rock
#

lol

wide shuttle
#

I don't think that's worthy of a ban but it also doesn't quite belong in this channel

unkempt rock
#

oh ok

#

where does it belong

wide shuttle
#

It's a #discord-bots-related example; do you have questions about it?

glass robin
#

has the purpose of the channel changed?

wide shuttle
#

No, the topic is still the same: advanced discussion of the Python programming language from a higher-level perspective

#

We're just experimenting with the name to see if that reduces the number of help questions that get posted here

undone hare
#

I've never looked at the internals of virtual environments before
@wide shuttle basically, it is copying the python core interpreter and symlinking all the other files it has to use to the system interpreter, just so when you enter the interpreter it is in a different folder than the system one, and it will look for site packages in another folders

#

But it is a really dirty hack, they are symlinks and actual files here and there, and it is messing with your path

peak spoke
#

How else would it work without messing with the path

undone hare
#

I mean, the whole venv system is hacky, I'm surprised we don't have any pipenv-like system built into the interpreter yet

full jay
#

Not to mention keeping it functional while still keeping the venv portable

undone hare
#

Like, activating nested venv will break your PATH for sure

full jay
#

Wall actually, it's funny you mention that, Ak

#

I think there is a spec for .pipfiles in one of the PEPs

#

So the structure is there, but it's just that there's been nothing built in for it. And I kind of get why.

wide shuttle
#

Pipfile?

#

I know there's for pyproject.toml

full jay
#

Hold on, now I'm second guessing myself

#

Ah no you're right

#

I knew it was one or the other

undone hare
#

Yeah pyproject is a thing, but I looked into it, the support isn't great, and the functionalities aren't too

wide shuttle
#

@undone hare Yeah, I know a bit how it works, but I've never looked at it in detail.

full jay
#

It's what poetry uses for its purposes

wide shuttle
#

pyproject.toml is pretty nice for packaging and publishing to PyPI

full jay
#

The use cases for poetry and pipenv are a bit different, and I find it hard to justify one being in the stdlib over the other, and even harder to justify having both in there. It makes more sense to have the core still be there (venv) and have other 3rd party libraries extrapolate from that

#

Because at the end of the day, all the solutions are still using venv

#

From my loose understanding, pipenv is better for what I consider "living" projects. Ones in constant active development like the site and the bot here. poetry seems to be better for packaged and distributed projects, like what you would put in PyPi

#

I think

undone hare
#

Yeah, making them into the stdlib would be silly, they don't belong here

#

But something that would automatically sync the requirements file before running code would be enough IMO, I just want to stop messing around with venvs

#

And some people never managed to make poetry working, and pipenv isn't getting any new update, so..

full jay
#

It is

#

Just slowly

peak spoke
#

pipenv is being worked on and there are very recent releases

full jay
#

Just not uploaded to pypi quite yet

#

But the last merged commit was 8 hours ago on pipenv's github

#

So there's still life in it

peak spoke
#

pypi has that release

undone hare
#

Fair enough

full jay
#

Oh does it?

#

Wait is that today?

peak spoke
undone hare
#

I'm still surprised that there is still no form of concurrent locking yet

full jay
#

Huh, I'll be damned

undone hare
#

Oh nice

full jay
#

Literally today

undone hare
#

Can you link the changelog please? :)

full jay
undone hare
#

That's pretty cool, thanks

#

pipenv install and pipenv sync will no longer attempt to install satisfied dependencies during installation.
Finally

full jay
#

Still looks like it's stuck on 3.7, though

#

But I guess that's not a huge issue

undone hare
#

Yeah, I don't think it is

#

It handles 3.9b1 just fine haha

full jay
#

I might fiddle with that then

unkempt rock
#

hello

#

has someone tried using pip with python compiled from source?

wide shuttle
#

Yes, I'm mainly using pip with versions of Python I've compiled myself

undone hare
#

I think pyenv is source compiling them, so me too

regal frigate
#

i am trying to understand cpython. do anyone can share links, tutorials, books so it can helpful for me.
thanks

full jay
#

@regal frigate What all are you trying to understand about it? And do you mean CPython the interpreter you get from the python.org site or do you mean Cython the compiler that uses Python as a base?

regal frigate
#

i already studied how interpreter works.. ie. lexer parser thing.
but when i look at cpython source i am not able to understand it.

#

i am interested in interpreter

#

i know that its not easy to understand. i am trying my best.

undone hare
snow kindle
#

I ask my self do I can with out publish put my own lib in pip libs ?

boreal umbra
#

For pathlib.Path, I feel like __bool__ should be the same as exists

flat gazelle
#

I can imagine some issues with PurePath, but it does not seem like a bad idea

boreal umbra
#

what's PurePath?

void sonnet
#

hmm. i don't initially disagree. but, yeah, i imagine there are some pitfalls.

peak spoke
#

Don't really like it as it involves an os call

flat gazelle
#

A class in pathlib that allows path manipulation without actually being able to interact with real files

sacred tinsel
#

eeh I'd probably end up doing if my_path: # If file exists lol

boreal umbra
#

Right now I have txt_path = potential_txt_path if potential_txt_path.exists() else None

#

but it could just be txt_path = potential_txt_path or None

void sonnet
#

my first question might be this: what is truthiness of a Path object?

boreal umbra
#

I assume they're always true. I'll check.

#
>>> from pathlib import Path
>>> scratch = Path("./scratch")
>>> bool(scratch)
True
>>> fake = Path("./asdf")
>>> bool(fake)
True
#

I don't have an asdf directory.

peak spoke
#

Not a fan of it because of the expensive call it does and not being really clear

full jay
#

The path only creates the appropriate file path, it doesn't check for its existence

#

And there's a logical reason for that

#

If you wanted to create a file at a certain location, you don't want it to fail because that location doesn't exist. You're going to be creating it, after all

boreal umbra
#

Also, isn't there a way to create a function that applies a certain operator between every object in a sequence?

#

I forgot the formula, except importing that operator's object from operator

flat gazelle
#

functools.reduce?

void sonnet
#

right. but having __bool__ wouldn't necessarily block that, would it Hem?

primal girder
#

It does have a .exists method

void sonnet
#

For pathlib.Path, I feel like __bool__ should be the same as exists

full jay
#

Fair

#

I'm not sure then

primal girder
#

So you can do

scratch = Path("./scratch")
print(scratch.exists())
full jay
#

^

#

I'm just not sure what the bool value is meant to imply

#

That is a fair point

#

I do think the .exists() method is more explicit, so no complaint on that front

peak spoke
#

The bool can be interpreted in multiple ways that make the same sense to the programmer without knowing more about Path

#

if path is not exactly clear imo unlike the exists method

flat gazelle
#

It is a bit different from all the other __bool__ in the standard library

void sonnet
#

i don't dislike the idea, but i can see the system call, as Numerlor points out, being an obstacle. my previous question was not worded well, and should've been more along the lines of what the expected truthiness of a Path object should be.

its clear (i think...) that it currently operates solely on the len(Path.__str__), which will always be true since an empty path is always eval'd as '.'.

primal girder
#

My only gripe with pathlib so far is needing to use str(scratch) to get at the path if you're needing to pass the path string to something.

flat gazelle
#

most python builtins take both Path and strings

paper echo
#

yep, imo any function that doesn't accept an os.PathLike instead of a string is in error imo

#

and it's silly that e.g. sqlite3.connect doesn't support it

#

(seems like an easy PR)

full jay
#

Wait wait wait, it can't? (also hey salt, I've missed you <3)

#

I'm assuming you can at least do str(os.Pathlike) and it'll take it, right?

molten onyx
#

Today I discovered a "weird" inconsistency in Python that I can only assume is due to special method lookup semantics:

>>> def _getitem(_, item):
...     if item <= 5:
...         return item
...     raise StopIteration
...
>>> class SillySequenceSemantics:
...     __getitem__ = _getitem
...
>>> for item in SillySequenceSemantics(): print(item)
...
0
1
2
3
4
5
>>> class Meta(type):
...     __getitem__ = _getitem
...
>>> class ClassLevel(metaclass=Meta):
...     ...
...
>>> for item in ClassLevel: print(item)
...
0
1
2
3
4
5
>>> class Inconsistency:
...     __class_getitem__ = _getitem
...
>>> Inconsistency[0]
0
>>> for item in Inconsistency: print(item)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not iterable```
boreal umbra
molten onyx
#

I don't think so no since this isn't CPython abuse

#

anyway I don't really consider it too noteworthy

#

if someone thinks it's BPO-worthy they can go ahead and open a ticket

primal girder
#

Your object needs to define __iter__() and __next__() to be iterable

peak spoke
#

it only needs iter to be iterable, and there is a fallback to a method that uses getitem as shown above

boreal umbra
#
    def count_tags(self) -> Counter[str, int]:
TypeError: 'type' object is not subscriptable
#

Did they not implement __class_getitem__ until 3.8?

primal girder
#

3.7

peak spoke
#

3.9 brings it to standard collections

#

above doesn't work for the same reason list[str] doesn't

boreal umbra
#

I thought the typing types in typing are just for builtins rather than stdlibs

peak spoke
#

there is a typing.Counter that you can use for the above

#

and the subscription behaviour will be brought to collections.Counter in 3.9

#

!pep 585

fallen slateBOT
#
**PEP 585 - Type Hinting Generics In Standard Collections**
Status

Accepted

Python-Version

3.9

Created

03-Mar-2019

Type

Standards Track

glass robin
#

typing module needs to be easier to read for function IMHO

peak spoke
#

What do you mean?

molten onyx
#

@primal girder the whole point of this demonstration was that you do not in fact need __iter__

#

I very much do not like the __getitem__ fallback system in Python

boreal umbra
#

what do you mean, the getitem fallback?

molten onyx
#

not needing an explicit __iter__ method to be iterable

spice pecan
#

I thought the fallback required __len__ as well

molten onyx
#

nope

#

if the class follows sequence semantics with __getitem__ alone (0, 1, 2, ... as indices) it is iterable

spice pecan
#

That's nice

boreal umbra
#

suppose you have a class that contains a subscriptable

#

could you just do

#

__getitem__ = self.some_thing.__getitem__?

peak spoke
#

you won't have access to self where that would be relevant

boreal umbra
#

oh good point.

boreal umbra
#

Another thing I noticed, there doesn't appear to be a simple way to import a module from its path as a string/os.PathLike

#

so I don't think you can do

#
>>> my_module = some_func('/path/to/my/file.py')
>>> my_module.another_func()
#

for any some_func that's defined in the stdlib.

true ridge
boreal umbra
#

I saw a similar solution elsewhere. I thought it looked a bit clunky, but I guess I just don't appreciate what the different steps are for.

peak spoke
#

for simple things this should work nicely

module_dict = runpy.run_path("file.py")
module=SimpleNamespace(**module_dict)
boreal umbra
#

is runpy a stdlib module?

peak spoke
#

yes

boreal umbra
#

😄

true ridge
#

It does a bit of abstraction, but yea runpy is nice.

peak spoke
#

while not that nice I think the snippet linked above is the "proper" way

true ridge
#

AFAIK they both run in the same way for normal source files (without silly details)

boreal umbra
#

I feel like there should be a one-function-call solution in importlib

rich wharf
#

I added more features to my iterable

#

The iterable class is very powerful

#

Nekit made a similar iterable class, the main difference is that their iterable class constantly depends on itertools.tee to clone the iterable

#

And tee isn't threadsafe

#

While mine depends on the user-provided state for how to act on the iterable

wide shuttle
#

Sure

#

Still, I'm trying to think of a good reason to do this

bold valve
#

how can i check for the message author role on discord server

wide shuttle
#

That isn't really a question for this channel, although the previous question wasn't probably either

narrow kettle
#

Current discussion is in general

bold valve
#

oh i wasnt sure ^^

wide shuttle
#

This channel is meant to discuss the Python programming language itself, from a more advanced/higher level perspective

#

Think of things like the implementation, advanced language features, PEPs, the future of the language

cloud crypt
#

interested to see python without GIL and with JIT haha

#

in the standard implementation, that is

primal girder
#

Probably gonna be a while. Removing the GIL adds a lot of overhead

cloud crypt
#

indeed it does, generally speeding python up will be a nice addition

gray mirage
#

The GIL is a speed optimisation though

#

That's why it's hard

spiral willow
#

GIL makes single thread faster

tacit hawk
#

what about subinterpreters, I saw one of the goals is to have one GIL per subinterpreter

peak spoke
#

python's speed benefits from the gil in probably more than 90% of its uses

#

The per interpreter gil seemed to be actively worked on last time I checked

spiral willow
#

in some cases, you can easily scale by spinning up multiple instances

#

like web hosting

cloud crypt
#

switching from python to rust and back feels so weird in terms of speed

rich wharf
#

nekit, your iterator uses tee a lot

#

so that's the main difference I saw with yours from mine

spiral willow
#

is rust significantly faster for your needs?

cloud crypt
#

well yeah I needed to copy an iterator

rich wharf
#

yeah, mine looks like it works differently in that case

cloud crypt
#

hm, and what do you do?

rich wharf
#

it either exhausts the original iterator

#

or it stores previously exhausted items

peak spoke
#

Last time I needed speed for something was a brute force algo fo some math that was easily solved by one numba decorator (or could've been solved by spending a bit more time on memoization)

rich wharf
#

or it converts the entire iterable to a list

cloud crypt
#

@spiral willow rust is just overall much faster, yet still provides some neat abstractions

rich wharf
#

depending on which state you set the iterator to

cloud crypt
#

ah okay

rich wharf
#

so it doesn't depend on tee

peak spoke
#

I do wonder why the speed keeps being brought up so much

cloud crypt
#

I don't remember how tee exactly works

rich wharf
#

itertools.tee(iterable) returns two copies of the iterable

#

but you can't use the original one

cloud crypt
#

yeah, yeah

#

but what does it do under the hood

rich wharf
#
def tee(iterable, n=2):
    it = iter(iterable)
    deques = [collections.deque() for i in range(n)]
    def gen(mydeque):
        while True:
            if not mydeque:             # when the local deque is empty
                try:
                    newval = next(it)   # fetch a new value and
                except StopIteration:
                    return
                for d in deques:        # load it to all the deques
                    d.append(newval)
            yield mydeque.popleft()
    return tuple(gen(d) for d in deques)

roughly this

#

also, tee iterators are not thread safe

cloud crypt
#

yeah I saw

rich wharf
#

so that's the difference between yours and mine

#

yours is easier to use with any iterator (you don't have to manually set a state), but mine is better for thread-safe cases

spiral willow
#

Sure

cloud crypt
#

I could also implement this at some point

#

I made that iter project for fun in like, several hours, without putting much thought :p

rich wharf
#

also I took some of your function ideas and put it in my iterator

cloud crypt
#

sure

rich wharf
#

like that funcmap method

spiral willow
#

I'd love to see CPYthon move to JIT

rich wharf
#

but I changed it a bit so that it's not a lambda

#

and seq.fmap('x, y', body) unpacks a single argument as x, y

#

instead of having two args

cloud crypt
#

I wrote func_map because someone told me they don't like writing lambda haha

rich wharf
#

mine is basically an equivalent version of yours

#

except instead of using 'x, y' as 2 args

#

it uses 'x, y' as unpacking 1 arg

#

and I think it's a neat idea

undone hare
#

What on earth is that

rich wharf
#

so you can do

#
seq = iterable([(1, 2), (3, 4), (5, 6)])
for i in seq.fmap('x, y', 'x + y'):
  print(i) #3 then 7 then 11
cloud crypt
#
from iter import iter
print(iter(range(10)).func_map("x", "x * x").chain_with("nekit").zip("lemon_ves_zappa").collect(dict))``` haha
rich wharf
#

what is chain_with?

#

oh wait

#

I see

cloud crypt
#

hm I don't actually remember if that is correct way haha

rich wharf
#
from iterable import iterable
print(
  iterable(range(10)).fmap('x', 'x ** 2').chain('nekit').zip('lemon_ves_lappa').collect(dict)
)
#

but I haven't added zip method yet

cloud crypt
#

aha

rich wharf
#

alright implemented

#

{0: 'l', 1: 'e', 4: 'm', 9: 'o', 16: 'n', 25: '_', 36: 'v', 49: 'e', 64: 's', 81: '_', 'n': 'l', 'e': 'a', 'k': 'p', 'i': 'p', 't': 'a'} I got this as my output

#

also with mine

#

you can replace .collect(dict) with .dict()

#
from iterable import iterable
print(
  iterable(range(10)).fmap('x', 'x ** 2').chain('nekit').zip('lemon_ves_lappa').dict()
)
cloud crypt
#

indeed

#

Iterator.collect(func) is just func that takes the iterator and does the job

rich wharf
#

yeah

cloud crypt
#

at some point I want to write a library with nifty extensions to standard classes and also adding nifty functions but idk how to call it

rich wharf
#

call it nifty

cloud crypt
#

haha

#
@extends(Iterator)
def zip(self, iterable):
    return self.__class__(zip(self, iterable))``` something like this, for example
rich wharf
#

I'm also going to work on a library I call ease

undone hare
#

That looks fun, even if I didn't understood everything haha

rich wharf
#

@undone hare iterable(range(10)) is a special class that handles iterators

#

.fmap('x', 'x ** 2') is equal to .map(lambda x: x ** 2) which is essentially equal to map(lambda x: x ** 2, the_iterable)

#

.chain('nekit') is the same as itertools.chain(the_iterable, 'nekit')

#

.zip('lemon_ves_lappa') is the same as zip(the_iterable, 'lemon_vas_lappa')

undone hare
#

Hmmmmmmmm

rich wharf
#

and .dict() is the same as dict(the_iterable)

cloud crypt
#

I think itertools.chain(the_iterable, *"nekit") though

rich wharf
#

not in my case

undone hare
#

So that's just a big boilerplate library to do funny functional things?

rich wharf
#
  def chain(self, *iters):
    return iterable(itertools.chain(self, *iters), state = self.state)
#

It's a convenient way to handle iterables

cloud crypt
#

call it as you want

#

lol

rich wharf
#

You can even copy iterables

#

iterable(range(10)).copy()

undone hare
#

I mean, the description can sound boring, but that's is pretty fun

cloud crypt
#

iterators, not iterables

rich wharf
#

what's the difference

cloud crypt
#

iterable is anything you can iterate over

#

including sequences, for example

undone hare
#

You should try to implement all the kotlin iterator functions haha

cloud crypt
#

iterator is something that can be generally exhausted

rich wharf
#

oh

cloud crypt
#

@undone hare my Iterator is inspired by std::iter::Iterator from guess the language

undone hare
#

C++?

cloud crypt
#

rust

undone hare
#

Ah I was going to say that haha

cloud crypt
#

@rich wharf I think I used chain_with wrong haah

undone hare
#

Forgot that you are the rust guy :>

rich wharf
#

I just made mine randomly inspired by JS

#

[1, 2, 3].map(x => x + 1)

cloud crypt
#

yeah I like => syntax

rich wharf
#

iterable([1, 2, 3]).map(x => x + 1)

#

yep, I want to get it added to Python

cloud crypt
#

though more a fan of ->

rich wharf
#

I like => slightly more

#

but either is good

cloud crypt
#

well I mean

#

if you think about it, you can implement => with tokens and encoding for now

#

haha

undone hare
#

One thing that would be pretty handy is to be able to convert dicts to lambda haha

{"var" : "print(var)"} ```->
```py
lambda var: print(var)```
rich wharf
#

really?

cloud crypt
#

yeah, why not

rich wharf
#

@undone hare you'd need a variable called var

undone hare
#

Well, you can do everything with custom tokens haha

#

True that

#

Like this

rich wharf
#
f = x => 5 + x
print(f(3)) #8
f = x => (
  if True:
    print(x + 3)
)
f(3) #prints 6
cloud crypt
#
# coding: arrow_lambda
func = x => x + 1``` can be translated to ```py
func = lambda x: x + 1```
rich wharf
#

yeah

#

would that work for my complex lambdas

flat gazelle
#

dict(var='print(var)') quoting dict keys is for suckers

undone hare
#

It would be very nice to not need one, but I don't think that would be any possible

rich wharf
#
f = x => (
  if True:
    print(x + 3)
)
f(3) #prints 6
cloud crypt
#

it has an if

#

so well, no I guess

rich wharf
#

oh well

cloud crypt
#

@flat gazelle this post was made by js gang

undone hare
spiral willow
#

nekit, well there goes all my RAM then

rich wharf
#

question

worldly hedge
#
f = x => (
  if True:
    print(x + 3)
)
f(3) #prints 6

@rich wharf seems like an arrow function Thonking

rich wharf
#

that's the point

#

how would you convert

'''
  if True:
    print(3)
'''
``` to
```python
'''
if True:
  print(3)
'''
#

like remove the lowest indent

undone hare
#

Dedent it?

#

There's a function for that

cloud crypt
#

why would you even do it

undone hare
#

!d textwrap.dedent

fallen slateBOT
#
textwrap.dedent(text)```
Remove any common leading whitespace from every line in *text*.

This can be used to make triple-quoted strings line up with the left edge of the display, while still presenting them in the source code in indented form.

Note that tabs and spaces are both treated as whitespace, but they are not equal: the lines `" hello"` and `"thello"` are considered to have no common leading whitespace.

Lines containing only whitespace are ignored in the input and normalized to a single newline character in the output.

For example:

```py
def test():
    # end first line with \ to avoid the empty line!
    s = '''\
    hello
      world
    '''
    print(repr(s))          # prints '    hello\n      world\n    '
    print(repr(dedent(s)))  # prints 'hello\n  world\n'
undone hare
#

Yeaaaahh

rich wharf
#

does that work for an arbitrary amount of them

undone hare
#

Yup

rich wharf
#
f = single_function(
    'x',
    '5 + x'
)

print(f(3))

f = single_function(
    'x',
    '''
if True:
    print(45)
    '''
)

f(6)
cloud crypt
#
sign = x => {
    if x < 0 {
        return -1;
    } elif x > 0 {
        return 1;
    } else {
        return 0;
    }
}``` now that I think about it...
rich wharf
#

I just got this to work

#

ahhh braces in Python

#

I like this more

#
sign = x => (
  if x < 0:
    return -1
  elif x > 0:
    return 1
  else:
    return 0
)
cloud crypt
#
# coding: braces
def square_int(x: int) { print("braces gang bois"); return x * x }```
undone hare
#

Parsers would not be happy about it afaik procez

rich wharf
#

I think it's possible to parse

#
sign = x => (
  if x < 0:
    return -1
  elif x > 0:
    return 1
  else:
    return 0
)
#

could be converted to

#
sign = x => (
if x < 0:
  return -1
elif x > 0:
  return 1
else:
  return 0
)
#

and it could parse that dedented inner-body just like any other python body

undone hare
#

I don't remember if the parenthesis tokens are discarded or not hmm

cloud crypt
#

how would you put it into a function

undone hare
#

No they are not, everything's fine

rich wharf
#
print(x => (
  if True:
    print(x)
))
#

or

undone hare
#

x => should be in the parenthesis IMO

rich wharf
#
print(
  x => (
    if True:
      print(x)
  )
)
undone hare
#

And future you will thank you for that

rich wharf
#

x => is ugly

#

x => (\n...\n) is better

undone hare
#

-> maybe?

rich wharf
#

x -> is ugly

#

x -> (\n...\n) is better

#
print(
  x ->
    if True:
      print(x)
)
undone hare
#

I mean

print(
  (x => 
    if True:
      print(x)
  )
)```
#

This

rich wharf
#

I prefer

#
print(
  x => (
    if True:
      print(x)
  )
)
#

I feel like surrounding the body is better

#

It just looks better

#

Your syntax looks like coffeescript

undone hare
#

F for backtracking

cloud crypt
#

how
do you
plan
to put
this
into the function body

rich wharf
#

wdym put this into the function body

#

@cloud crypt can you elaborate

#

i'm confused

cloud crypt
#

lambdas can not contain statements

rich wharf
#

oh, that's what you mean

#

it'll try to evaluate it as an expression first

#

but if it fails and there are (), it'll evaluate it as statements

#
x => (5 + x) #treated as expression
x => (return 5 + x) #treated as statement
cloud crypt
#

how would you make python understand it is a function

undone hare
#

I'm pretty sure making multi-line lambdas is just a matter of changing 3 lines in the grammar file haha, like the relaxed decorator syntax was

rich wharf
#

it would be built into the syntax?

undone hare
#

With some internal calls I'm pretty sure that would be possible

rich wharf
#

not the current python implementation

#

but if you changed python's grammar and parsing you could

cloud crypt
#

well who is against you forking cpython

#

except the size LOL

undone hare
#

It is just the grammar here

#

It is really small actually haha

#

The whole work dir is 30Mb

cloud crypt
#

of lines

undone hare
#

I don't know for the repo itself though

#

Do you count your disk usage with lines? blobthinkingdown

rich wharf
#

alright I added a new feature to my iter class

#

(renamed it to iter)

undone hare
#

F for the built in iter?

rich wharf
#

f

cloud crypt
#

new iter is just iter but with wrapping

#

lol

rich wharf
#

but why would need it when you have mine

cloud crypt
#
from iter import iter
print(iter([1, 2, 3, 4, 5]).join(", "))``` js gang
rich wharf
#

you added join?

#

I need to implement that ahh

#

also

cloud crypt
#

a while ago

#

ahah

rich wharf
#

I want to add this

#

iter[1, 2, 3, 4, 5].join(', ')

cloud crypt
#

ah that's simple

rich wharf
#

yeah, hooking into getitem

#

and this

#

iter(1, 2, 3, 4, 5) being equal to iter((1, 2, 3, 4, 5))

cloud crypt
#

metaclass go weeeeeeeeeeee

rich wharf
#

yep

undone hare
#

All the iter functions are still lazy, right?

cloud crypt
#

yeah

rich wharf
#

yeah

undone hare
#

That's pretty cool

cloud crypt
#

I am not familiar with thread-safety, but why is tee unsafe

undone hare
#

You have things like filter, sort, group, and funny functions like that?

rich wharf
#

I have filter

cloud crypt
#

sort is uh

#

no

rich wharf
#

not sure about sort and group

cloud crypt
#

group is what

rich wharf
#

I also have an apply function

#

which takes in the item

#

and returns a tuple (keep, new_value)

undone hare
#

Make a dict based on the return value of a lambda

rich wharf
#

I have .dict()

#

which is like dict(iterable)

undone hare
#

A dict -> list -> values with the same output

cloud crypt
#

I thought .collect(list|dict|set) is fine

rich wharf
#

I have both

cloud crypt
#

@undone hare what did you mean under group function though

rich wharf
#

.collect(list)

#

.list()

undone hare
#

Sort wouldn't be lazy yeah, but that would be really useful

rich wharf
#

I'll add it

cloud crypt
#

oh I know, I know

undone hare
#

You have a dict output -> list, where all the values in a list have returned the same output through a lambda

#

Time to go to bed, cya guys! pyllow

cloud crypt
#
import gc
gc.get_referents(object.__dict__)[0].update(iter=lambda self: iter(self))```
#

esoteric but magical

#
print([1, 2, 3, 4, 5].iter().map(lambda x: x * x).step_by(2).join("-"))```
undone hare
#

wut

rich wharf
#

wait does that work

cloud crypt
#

mhm

rich wharf
#

!e

import gc
gc.get_referents(object.__dict__)[0].update(into_iter=iter)
print([1, 2, 3, 4, 5].into_iter().map(lambda x: x * x).step_by(2).join("-"))
fallen slateBOT
#

You are not allowed to use that command here. Please use the #bot-commands channel instead.

cloud crypt
#

please don't do that in production tutu

rich wharf
#

alright

cloud crypt
#

I am still wondering what Akarys meant under group

rich wharf
#

same

#

wait question

#

if we can add .iter

#

why not just add all of the methods to existing objects

#

[1, 2, 3].map(lambda i: 1 + i)

cloud crypt
#

I mean you can

#

but you would need to convert it to iter

rich wharf
#

so what

#

[1, 2, 3].map(lambda i: 1 + i) could return an iter object

cloud crypt
#
assert iter.new(1, 2, 3, 4).chunk(2).collect(dict) == {1: 2, 3: 4}``` I think he meant this under groups
rich wharf
#

wait

#

does .chunk(2) split it into two chunks

#

or chunks of size 2

cloud crypt
#

two chunks

rich wharf
#

I have a dif method name for that

#

.partition(2) splits it into chunks of size 2

#

.split(2) splits it into 2 chunks

#

both have optional remainder methods

cloud crypt
#

fun

rich wharf
#

I'm going to add a likely_max() method

cloud crypt
#

so we're essentially copying each other's work

rich wharf
#

yeah haha

cloud crypt
#

except that I don't have your source LOL

rich wharf
#

I can put it on git rn

#

but likely_max() will work like this

#

it looks for round(len(iterator) / math.e + .5) items

#

and then gets the biggest item after that

#

so it gets the likely max item without going through every item

cloud crypt
#

how would you get length of an iterator

rich wharf
#
  def __len__(self):
    return len(self.array)
#

self.array is a property that only works for iterators of state sequence

cloud crypt
#

ah well

rich wharf
#

so only iterators that allow you to convert it to a list before starting

#
  @property
  def array(self):
    self.block(state = 'sequence')
    if self._array is None:
      self._array = list(self.obj)
    return self._array
cloud crypt
#

just put it on GitHub lemon_pleased

rich wharf
cloud crypt
#

ah so ease

rich wharf
#

yeah, basically a collection of random python modules I made

cloud crypt
#

type(self) < self.__class__

rich wharf
#

why?

#

@cloud crypt why is self.__class__ better

cloud crypt
#

it is faster

rich wharf
#

alright

cloud crypt
#

and in almost all cases the same as type(self)

rich wharf
#

ok, I'll switch

cloud crypt
#
  def all(self):
    return sum(self)``` when Procez codes too fast
rich wharf
#

haha

cloud crypt
#

I feel like we could go to DM’s since we are the only participants here KarenWhat

rich wharf
#

sure

rich wharf
#

I made some code that gets this to work on CPython (maybe PyPy too)

#

SOURCE

for (current, after) in range(10).context(count = 1):
  print(current, after)

OUTPUT

0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
twilit garnet
#

did you add an entry to range's __dict__ with ctypes?

#

i think i did similar things using a helper module that i didn't complete

rich wharf
#

not just ranges

#

gc.get_referents(object.__dict__)[0].update(...)

twilit garnet
#

:D

rich wharf
#

huh

#

@twilit garnet it actually works by converting the object to a class and then calling the method from the class object

#

you can do range(10).context(count = 1) with the trick

#

or iter(range(10)).context(count = 1)

twilit garnet
#

yeah, my method allows that too theoretically

#

since it does the same thing

#

modifies the same attribute, i mean

#

mine is just a bit hackier, though

rich wharf
#

that's from a really long time ago

twilit garnet
#

haha yeah

rich wharf
#

my goal though is to make a convenient iterable class

twilit garnet
#

i used to do a lot of stuff like that back then, haven't had much motivation since then

rich wharf
#

I think this is readable and convenient

twilit garnet
#

kinda like rust's iterables?

rich wharf
#

I haven't seen them

twilit garnet
#

oh they're fucking beautiful

#

i once made an entire math expression parser using just a single chain of iterator methods

rich wharf
#

interesting

#

wait what

#

an entire MATH expression parser

twilit garnet
#

it was a simple one

#

and there were some frills that weren't included in the iterator chain

#

but it was still mostly put to work with the iterator IIRC

rich wharf
#
for i in iter([1, 2, 3, 4, 5]).context(count = 1).fmap(
  'item, after', '{"item": item, "after": after, "sum": item + after}'
):
  print(i)

Output

{'item': 1, 'after': 2, 'sum': 3}
{'item': 2, 'after': 3, 'sum': 5}
{'item': 3, 'after': 4, 'sum': 7}
{'item': 4, 'after': 5, 'sum': 9}
#

These are an example of my iterables

#

(item, after) is the item that we're iterating over, and then the item after it

#

.fmap is a good function when you need to unpack variables

#

.map doesn't let you unpack values

#

I'm going to check out rust iterables

twilit garnet
#

looks a lot like iterators in rust to me haha

#
TokenKind::Identifier => string
    .char_indices()
    .take_while(|&(_, chr)| chr.is_ascii_alphabetic())
    .last()
#

(don't hurt me mods, i'm just using this as a comparison! :D)

rich wharf
#

I'm going to add .peek to my iterables

twilit garnet
#

but still, modifying builtins like this is definitely more on the lines of #esoteric-python, to be honest.

rich wharf
#

yeah, but I'm not talking about modifying builtins

#

I'm talking about my general iterables now

#

which is on the topic of advanced python

twilit garnet
#

oh sure, that's fair.

brave badger
#

.fmap is a good function when you need to unpack variables
@rich wharf What does the f in fmap stand for?

rich wharf
#

funcmap

#

since it generates a function

brave badger
#

Ah I see, kinda confused it with Haskell's fmap for Functors

rich wharf
#

alright

#

I'm going to take a bunch of rust's functions for iterators and add them to my class

twilit garnet
#

i can approve of that

rich wharf
#

I added a few new methods

#

peek

#

skip_while

#

take_while

#

try_map

#

try_filter

#

find

#

sort

#

cycle

deft pagoda
#

we made a peekable a week or two ago

rich wharf
#

we who is we?

north root
#

peekable iterator? that was cool

deft pagoda
#

i don't remember exacts, but i have the file

rich wharf
#

ok

#

who else made it?

rich wharf
#

also

#

peekable can be done using tee

deft pagoda
#

yep, but i used a deque

#

because you can pass in a default value when you peek if you want

rich wharf
#

huh

deft pagoda
#

if the iterable is exhausted

#

we also had the .__ magic

#
In [134]: a = peekable(range(100))

In [135]: a._
Out[135]: 0

In [136]: a.__
Out[136]: 1

In [137]: a.___
Out[137]: 2
#

this is kind of cute

rich wharf
#

I don't like it ahhh

#

but it's interesting

#

I'm going to add a .some method

deft pagoda
#

well, the most often used mode is .peek(1) so we just shortcut to ._

rich wharf
#

for me, it's just .peek()

#

you can't go further

#

but I'll add that option

#

also I'm going to do .peek(0) for starting

#

not .peek(1)

deft pagoda
#

peek(0) returns a () for what we ended up with

rich wharf
#

alright

deft pagoda
#

peek() returns the next item, and peek(n) returns a tuple of length n

rich wharf
#

oh

#

I think I'll implement that too

#

since it's a good idea

#

anyways I'm going to add in .some

deft pagoda
#
In [138]: a = peekable(range(3))

In [139]: a.peek(5, default='python')
Out[139]: (0, 1, 2, 'python', 'python')
unkempt rock
#

?

#

i just learned printing today XD

rich wharf
#

This is a more advanced channel @unkempt rock

#

So you might not get the examples

#
seq = iter(range(10))

for i in seq.some(lambda i: i ** 2 if i != 5 else None):
  print(i)

Output

0
1
4
9
16
#

Should I do that

#

Or

#
seq = iter(range(10))

for i in seq.some(lambda i: i == 5).map(lambda i: i ** 2):
  print(i)

Output

0
1
4
9
16
unkempt rock
#

k

rich wharf
#

I think I'm going to do the latter

deft pagoda
#

should implement islice as a __getitem__

rich wharf
#

alright

#

and I'm going to implement peek defaults too

#
for i in (
  iter(range(10))
  .context(count = 2)
  .fmap('a, b, c', '{"a": a, "b": b, "c": c}')
  .some(lambda i: i['a'] == 5)
):
  print(i)

Output

{'a': 0, 'b': 1, 'c': 2}
{'a': 1, 'b': 2, 'c': 3}
{'a': 2, 'b': 3, 'c': 4}
{'a': 3, 'b': 4, 'c': 5}
{'a': 4, 'b': 5, 'c': 6}
{'a': 5, 'b': 6, 'c': 7}
brave badger
#

What could be a rational way of implementing Scala's placeholder syntax e.g. List(1, 2, 3).map(_ + 2)? I'm currently managing the arithmetic operations as a list and then processing it through there.

rich wharf
#

@brave badger Maybe have _ be some sort of Placeholder object

#

With __add__ and __sub__ and etc methods

brave badger
#

Yeah I have those, was thinking of a better way of managing the functions

rich wharf
#

Wdym?

#

You mean func(_)?

#

func(placeholder) could be converted to placeholder.call(func)

brave badger
#

The _Wildcard class I have has a func list attribute that holds all of the functions of which I compose by iterating through them

rich wharf
#

I think that's fine

brave badger
#

I have to somehow preserve operator precedence though, since having _ + _ * _ would mean a list of [add, mul]

rich wharf
#

That might be tricky

#

@brave badger I think that's quite esoteric though, maybe that's more of an #esoteric-python project

brave badger
#

I could use the easy route and write a parser that builds the function for me pithink

rich wharf
#
for i in (
  range(15)
  .context(count = 4)
  .fmap('a, b, c, d, e', '{"a": a, "b": b, "c": c, "d": d, "e": e}')
  .some(lambda i: i['a'] == 7)
):
  print(i)

Output

{'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4}
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
{'a': 2, 'b': 3, 'c': 4, 'd': 5, 'e': 6}
{'a': 3, 'b': 4, 'c': 5, 'd': 6, 'e': 7}
{'a': 4, 'b': 5, 'c': 6, 'd': 7, 'e': 8}
{'a': 5, 'b': 6, 'c': 7, 'd': 8, 'e': 9}
{'a': 6, 'b': 7, 'c': 8, 'd': 9, 'e': 10}
{'a': 7, 'b': 8, 'c': 9, 'd': 10, 'e': 11}
merry pollen
#

@brave badger if you want to preserve precednece order you should probably represent your function chaining as a tree or smth

#

and then resolve it at the end

#

actually no

brave badger
#

I kinda cheated by using eval

>>> (_ + _ * _ * _)(5, 5, 5, 5)
130
merry pollen
#

oh well, that works bloblul

brave badger
#

I need to make it safe though because the func attribute can be tampered with

merry pollen
#

i think you could do it with function chaining though

#

hmn

rich wharf
#

alright

#

@tardy badge I think you should get a help channel for this

tardy badge
#

apologies

rich wharf
#

no apologies needed, you're fine

paper echo
#

havent people done things like that in e.g. macropy?

#

make _ mean something special

#

and hope your users dont overwrite it

#

but it causes a lot of issues because fundamentally there are certain things for which you cannot "defer" evaluation

#

whereas with actual macros (or arbitrarily overridable operators) that isnt a problem

#

its a fundamental python limitation. kind of frustrating if you're a tinkerer, but its also helpful to have certain limits

golden imp
#

If you're not married to having _ as the placeholder, could probably implement something with

#
from fancylib import VAR1, VAR2, VAR3
func = VAR1 + VAR2 * VAR3
#

or the like

rich wharf
#

you could do

#
from fancylib import args
func = args[0] + args[1] + arg[2]
deft pagoda
#

you can use sympy for that too

golden imp
#

oh that too

rich wharf
#
print(
  iter(range(10))
  .replace(5, '5 is a number')
  .list()
)

Does anyone have other iterator suggestions?

golden imp
#

or even

from fancylib import arg
func = arg() + arg() * arg()
twilit garnet
#

doing it even without the parentheses would be easy enough i think.

rich wharf
#

yeah

deft pagoda
#
In [182]: from sympy import var

In [183]: x, y, z = var('x,y,z')

In [184]: x + y + z
Out[184]: 
x + y + z
rich wharf
#

sympy can do that?

#

that's interesting

deft pagoda
#

sympy has a lot of nice things going on

rich wharf
#

what new methods should I add to my iterators

boreal umbra
#

Bogosort

rich wharf
#

seriously

#

bogosort is||n't|| useful, but still

deft pagoda
#

bogosort the most efficient sort ever

rich wharf
#

but seriously, what should I add to it

#
seq = iter(range(10))

for i in (
  seq
  .context(count = 2)
  .fmap(
    'x, y, z',
    '''
      if True:
        return {'x': x, 'y': y, 'z': z}
      else:
        return {'x': None, 'y': None, 'z': None}
    '''
  )[::-2]
):
  print(i)
#

right now that works, and it outputs

#
{'x': 7, 'y': 8, 'z': 9}
{'x': 5, 'y': 6, 'z': 7}
{'x': 3, 'y': 4, 'z': 5}
{'x': 1, 'y': 2, 'z': 3}
#

but I want to make it useful

#

more useful

#

by adding more features and methods

grizzled vigil
#

I've personally never been a fan of the "Fluent" style of programming that involves chaining together multiple methods like that. It can work for quick scripts and can be useful in something like a REPL where it never gets directly used again, but IMO it makes debugging more painful for no real gain. I'll admit that it looks decent from the perspective of concisely describing what the code does, I just don't find it to be worthwhile in "real-world" code, especially as the complexity of the chained operations become non-trivial.

golden imp
#

spark lol

grizzled vigil
#

That's just my opinion though; it's rather popular in C# (LINQ) and JS ecosystem.

spark parcel
#

What do you mean with “fluent”?

grizzled vigil
raven ridge
#

SomeClass().withSomeAttribute(value).andSomeOther(value2)

flat gazelle
#

I do prefer it over large expressions written with the usual fun() form. Generally, having sizable expressions is not ideal though.

spark parcel
#

Okay, I’ll take a look

grizzled vigil
#

@flat gazelle Yeah, I can see that. I don't think it's inherently a bad style of programming, I just try to avoid it for the most part since I find that it tends to make the code harder to change later or debug. If I'm performing too many operations in a single function or repeating them over and over, I'd rather create a separate function/method instead of chaining a bunch of calls together.

flat gazelle
#

It does make sense in some cases in java where you would use kwargs in python/kotlin. But yes, it can get messy, especially in kotlin, which encourages that to an almost excessive extent

rich wharf
#

how else would you suggest I do what I did

#

seq.map(lambda i: i ** 2).context(count = 2).collect(list)

#

without the attrs

#

maybe ```python
seq.manage(
map = lambda i: i ** 2,
context = 2,
collect = list
)

#

but ordered kwargs doesn't work in all languages

#

versions

vital vine
#

Is it possible to add a getter-setter to a variable dynamically?
Without pre-defining it in the code

merry pollen
#

wdym

#

a getter/setter for a like, standalone variable?

#

or like, an instance variable?

vital vine
#

I want to detect when a variable gets changed without defining a getter setter at least by default

class Foo:
  bar = None

And the program makes bar a property so it can detect when it gets called or set to another value

rich wharf
#

use property

#
class Foo:
  @property
  def val(self):
    return self._boo
  @property.setter
  def val(self, value):
    self._boo = value
merry pollen
#
class Foo:
  ...
a = Foo()
a.boo = property(getter_function)
a.boo.setter(setter_function)

would work, but

#

why

#

or at least i hazard it would work

brave badger
#

That would require writing decorating each attribute though, in terms of not defining a getter/setter by default, you could probably do some automation with metaclasses/plain parent classes

vital vine
#

Thanks guys, I'll try them 😄

merry pollen
#

oh nop does not seem to work

#

oh you add it to the class

#

huh

dire hull
#

so in the docs of pickle it says JSON can only represent a usbset of python build-in types and no custom classes

merry pollen
#

descriptors.. wacc

dire hull
#

does this mean that it also cannot serialize class instances created from custom classes?

merry pollen
#

i mean, json certainly can't

dire hull
#

but it says json is used everywhere

merry pollen
#

it indeed is

dire hull
#

so if i pickle objects to binary then i can onyl read it from python

merry pollen
#

yup

dire hull
#

also pickle is not human readable welp

merry pollen
#

also yup

dire hull
#

this is like very suc

merry pollen
#

you can try jsonpickle

#

which will pickle the bits that have to be pickled and json the rest

dire hull
#

so if there are only custom class isntances then its just all piclkle?

#

lol i feel like this is slightly better but welp

merry pollen
undone hare
#

Pickle isn't safe too

#

By modifying it, you can make it run any code

#

It can be really dangerous in some cases

dire hull
#

yeah i read about it but since im still learning the ropes ill ignore that part for now

#

lol

#

actually come to think of it i should probbly just store the inputs and create objects reading those inputs to avoid this and make the serialized file readable

#

welp

undone hare
#

Well, pickle is easily readable, even if that's not a plain text format

#

Someone could just fire up an interpreter and load the file

dire hull
#

i see

undone hare
#

If you don't share your source code, the best way to do it is to drop all your attributes as raw hexadecimal numbers in a file, so without the source code it is almost impossible to know what is what, and it should be pretty easy to parse

vital vine
#

Why is that when I use the property() function to set a variable to a property in a function and not in the root of a class it'll be just a property class and doesn't actually work as a property? (I mean I can only get its value with var.__get__(self) and not just with var)

dire hull
#

ill look into that thx!@undone hare

molten onyx
#

@vital vine how exactly are you using it? I don't quite understand

#
>>> class C:
...     ...
...
>>> def getter(self):
...     return 10
...
>>> def setter(self, val):
...     print(val)
...
>>> C.x = property(getter, setter)
>>>
>>> c = C()
>>> c.x
10
>>> c.x = 11
11```
vital vine
#
class Foo:
  bar = None

class A:
  def __init__(self):
    def _getter(self):print("Getter called")
    def _setter(self, v):print("Setter called")
    Inst = Foo()
    Inst.bar = property(_getter, _setter)
molten onyx
#

ah, this is because your getter and setter are bound to A already

#

wait no that's in __init__

vital vine
#

yeah

molten onyx
#

It's because you set the property to the instance instead of the class

vital vine
#

ah I see

#

Thanks 🙂

celest juniper
#

How difficult is python GUI and what would be the best route to take for learning it? I remember I stumbled upon one GUI library once upon a time but it barely had a KB / documentation

rich wharf
#

@celest juniper There's a few options for it, and Python isn't the best for it but Python can do it decently well

#

Tkinter, PyQt, WtPython and etc are a few options if I remember

#

I'm making a simple GUI library as well

#

Kivy as well

fossil jetty
#

why is it faster to write out CSVs iteratively vs. with multiprocessing.pool? As far as I can tell, my RAM, CPU, and disk are are far below 100%... Shouldn't multiprocessing make it faster by writing on a separate process?

i.e. I should be able to write as many CSVs as pool executors in 1/n the time

celest juniper
#

What language would you say bests supports GUI interfaces? @rich wharf

rich wharf
#

I'm not sure

#

Python has some good options but it's not the absolute best

#

It isn't bad either though

wide shuttle
#

why is it faster to write out CSVs iteratively vs. with multiprocessing.pool? As far as I can tell, my RAM, CPU, and disk are are far below 100%... Shouldn't multiprocessing make it faster by writing on a separate process?

i.e. I should be able to write as many CSVs as pool executors in 1/n the time
@fossil jetty

What's limiting your writing speed? Probably not your CPU, but your disk. Adding more CPU overhead won't make your harddisk write data faster.

fossil jetty
#

But SSD reports 2% usage?

#

the constraint is SSD write speed, but my disk is showing ~1MB/s write

#

random writes should be in the ~100MB/s range?

wide shuttle
#

I'm not sure what's limiting your writing speeds, but unless you do a lot of preprocessing on the spot during your write iteration, I doubt your task is CPU bound

spiral willow
#

because disk is likely bottleneck but Windows won't always show it at 100% even when it's effectively bottlenecked

#

esp if it's a spinny disk

#

++, no, multithreading can make it worse as multiple applications keep sending interrupt requests for disk time

#

esp it's line by line

#

at my company, we write out large CSVs from DB results, we found single threaded to be much better for performance so all CSV create jobs are loaded into ServiceBus where exporter process runs SQL command to execute the CSV write then moves the files to proper place.

sturdy timber
#

What was the change that meant you could you not assign to True or False? I'm sure you used to be able to but now it gives a SyntaxError?

flat gazelle
#

I would guess they became literals instead of builtins

wide shuttle
#

The change was made in the transition to 3.0, if you want to dig into it. True and False were probably given what was already implemented for None

sturdy timber
wide shuttle
#

In Python 2.2, True and False were introduced, but just as "constants" assigned to 1 and 0. The bool type was introduced in 2.3.

boreal umbra
#
>>> PathLike = t.Union[os.PathLike, str]
>>> isinstance("hi", PathLike)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/typing.py", line 711, in __instancecheck__
    return self.__subclasscheck__(type(obj))
  File "/usr/local/lib/python3.7/typing.py", line 719, in __subclasscheck__
    raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks
#

Is there anything that supports this behavior, or am I just abusing the type checker?

grave jolt
#

I thought this was supported 🤔

boreal umbra
#

this is 3.7

#

not sure if that matters

grave jolt
#

!e

from typing import Union
from os import PathLike
PathLike = Union[PathLike, str]
print(isinstance("hi", PathLike))
fallen slateBOT
#

@grave jolt :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 4, in <module>
003 |   File "/usr/local/lib/python3.8/typing.py", line 766, in __instancecheck__
004 |     return self.__subclasscheck__(type(obj))
005 |   File "/usr/local/lib/python3.8/typing.py", line 774, in __subclasscheck__
006 |     raise TypeError("Subscripted generics cannot be used with"
007 | TypeError: Subscripted generics cannot be used with class and instance checks
boreal umbra
#

😦

peak spoke
#

Why do you need str and path like union?

boreal umbra
#

Because one could use either sometimes.

peak spoke
#

a str path is path like

grave jolt
#

nope

boreal umbra
#

nope

#

I discovered this recently

#

I had just finished a new release version of my package and it crashed when I used the CLI

unkempt rock
#

what is that font?

grave jolt
#

Hasklig Black

unkempt rock
#

ok, this one I can read

#

not like I understand it or anything

grave jolt
#

I like this one better, actually

rich wharf
#

I'm making a package with modules that make Python "easier".

astparse - Allows you to use a helper class to more easily parse ast.
map - Allows you to create dictionaries with more methods and allows . item setting and getting
decorators - Makes creating decorators that attach information to functions easier, as well as making general decorators
iter - Adds plenty of methods to make iteration easier
timespan - A convenient way to define and manage timespans that shows you the years, days, hours, minutes, seconds, etc of the timespan.

chains - Allows you to define anonymous functions with attribute and method chaining
lambdatools - Allows you to define anonymous functions using functions that take in lambdas

Those are some of the existing ones I have, does anyone have suggestions for new ones I should make?

grave jolt
#

Maybe you should post that in open-source-collaboration/show-your-projects and leave a permanent link to some repo, so that people can post some suggestions

rich wharf
#

Huh, maybe.

whole rune
#

HI there! i need help dealing with browsers, if anyone available can help me pls pm me

rich wharf
#

This isn't the channel for that

magic python
#

@rich wharf what's an example from iter

rich wharf
#
for c, i in (
  iter([1, 2, 3])
  .map(lambda i: i ** 2)
  .enumerate()
):
  print(f'count {c}: {i}')
>>> count 0: 1
>>> count 1: 4
>>> count 2: 9
#

@magic python

#

iter is compatible with the builtin iter function

magic python
#

is the 0,1,2 intentionally shifted from 1,4,9?

rich wharf
#

yeah

#

[1, 2, 3] and list(range(3)) aren't equal

#

was just showing that as an example

#

there's more methods like .sample, .shuffle, .filter, .peek, __next__, __len__, you can use __getitem__ for items or slices, etc

whole rune
#

thank you @rich wharf

rich wharf
#

@whole rune no thanks necessary

stoic bone
#

I have a math question, sort of, to do with random floats between [0.0, 1.0). So I'm looping through an array of strings, and I have a function that I call that returns True or False based on a random float between [0.0, 1.0). I want to make it so that the closer it is to the end of the array of strings, the more and more likely it is that the function will return True. But I need to do so in a way that's exponential, not linear. So until you get to the last 10-20% of the array, the likelihood only increases slightly but once it gets to that area the likelyhood increases drastically until the last few entries it's almost a certainty that it will return True

prime estuary
#

@stoic bone Well the way you'd do that is produce an exponential equation that is 1 at the end, and 0.2 (or whatever) at the start. Then compare if random() < equation(pos). That would trigger 20% of the time at the start, 100% at the end.
To create the equation, what you need is the "standard" equation y = a*exp(b*x). a and b are constants, which you can figure out with some algebra. First feed in x=0, your desired y (0.2?) and find a. Then add x=1 (or whatever), the desired y=1 and solve for b. Rearranging produces b = logn(y/a)/x.

stoic bone
#

y = a ** (b * x) you mean?

prime estuary
#

That would also apply, I was assuming you meant ae^bx.

cedar latch
#

anyone used textgenrnn

shut anchor
#

I've done textgen with weighted random predictive stuff. Not an rnn, but the results aren't that different.

#

It wrote goose poetry.

#

and ribald Grimm's fairytales.

rich wharf
#

I prefer GPT2 now, but yes I have

#

gpt-2-simple

#

made by the same guy as textgenrnn

#

not the model, but the library

cedar latch
#

it it better and easy to implement

humble finch
#

How to use future annotations?

#

PEP 563

boreal umbra
#

@humble finch I believe it's just from __future__ import annotations

#

As the first line of the file.

north root
#

the future annotations are quite nice

boreal umbra
#

Speaking of which, I remember reading that annotations were originally introduced to store arbitrary data rather than type hints. Why is that?

cedar latch
#

gpt-2-simple
@rich wharf is it pretrained?

rich wharf
#

@cedar latch yep

#

but it can be finetuned

cedar latch
#

its it better?