#esoteric-python
1 messages · Page 90 of 1
A feature I would love to see is jumping to CPython code when you click go to definition on a built-in function/class.
Hmm, I wonder how would that work
Tracing the C implementation can be quite challenging
There probably is a plugin that lets you do that, or at least it shouldn't be that hard to write
WTF
Got it, it is (1 in {0, 1}) and ({0, 1} in {0, 1})
because it treats in like a comparison operator
that doesn't matter here
the point is that a in b in c is neither (a in b) in c nor a in (b in c)
yikes
Looks like if you talk about pure operation precedence it should be parsed as a in (b in c), but the () are probably messing with the parser here : https://docs.python.org/3/reference/grammar.html
comparison: expr (comp_op expr)*
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'```and `comparaison` is going up some operator precendence chaines up ot `test`
Which itself is an argument
well, it's not even treated as a binary operation
just like a < b >= c is (a < b) and (b >= c), 1 in {0, 1} in {0, 1, 2} is (1 in {0,1}) and ({0,1} in {0,1,2})
you can use ast to prove it
!e
import dis
def f():
return (0 in {0, 1, 2} in {0, 1, 2})
dis.dis(f)
huh, only one set... and a frozenset?
I don't understand why it doesn't turn {0,1,2} into a frozenset
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | 4 0 LOAD_CONST 1 (0)
002 | 2 LOAD_CONST 1 (0)
003 | 4 LOAD_CONST 2 (1)
004 | 6 LOAD_CONST 3 (2)
005 | 8 BUILD_SET 3
006 | 10 DUP_TOP
007 | 12 ROT_THREE
008 | 14 COMPARE_OP 6 (in)
009 | 16 JUMP_IF_FALSE_OR_POP 24
010 | 18 LOAD_CONST 4 (frozenset({0, 1, 2}))
011 | 20 COMPARE_OP 6 (in)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/iwefenivih
!e py import dis dis.dis(lambda x: x in {1,2,3}) dis.dis(lambda x: {1,2,3} in x)
@stark fable :white_check_mark: Your eval job has completed with return code 0.
001 | 2 0 LOAD_FAST 0 (x)
002 | 2 LOAD_CONST 1 (frozenset({1, 2, 3}))
003 | 4 COMPARE_OP 6 (in)
004 | 6 RETURN_VALUE
005 | 3 0 LOAD_CONST 1 (1)
006 | 2 LOAD_CONST 2 (2)
007 | 4 LOAD_CONST 3 (3)
008 | 6 BUILD_SET 3
009 | 8 LOAD_FAST 0 (x)
010 | 10 COMPARE_OP 6 (in)
011 | 12 RETURN_VALUE
<value> in <set> is guaranteed to have the same behaviour as <value> in <frozenset>
but <set> in <value> might not have the same behaviour as <frozenset> in <value>
>>> class Weird:
... def __contains__(self, obj):
... return isinstance(obj, set)
...
>>> {1} in Weird()
True
>>> frozenset({1}) in Weird()
False```
got it
Anyone have any clue as to why this func to preform min, max is preforming faster than the builtins?
import timeit
iterations = 1000
t = timeit.Timer(stmt="min(10,20)+max(10,20)")
test = sum(t.repeat(iterations))/iterations
print(test)
# >> 0.2002716760898329
setup = """
def fl(a,b):
return ( (a>=b)*a ) + ( (a<b)*b )
def fs(a,b):
return ( (a<=b)*a ) + ( (a>b)*b )
"""
t1 = timeit.Timer(stmt="fl(10,20)+fs(10,20)", setup=setup)
test1 = sum(t1.repeat(iterations))/iterations
print(test1)
# >> 0.17918118402005348
setup2 = """
def f(s,a,b):
t = 0
if(a<b):
t += ((s=='s')*a) + ((s=='l')*b)
else:
t += ((s=='l')*a) + ((s=='s')*b)
return t
"""
t2 = timeit.Timer(stmt="f('l',10,20)+f('s',10,20)", setup=setup2)
test2 = sum(t2.repeat(iterations))/iterations
print(test2)
# >> 0.25543811730007293
Feel free to tag me if you have any insight into it :]
the builtin min/max are quite complex as they rae for iterables instead of picking from two vals
https://github.com/python/cpython/blob/master/Python/bltinmodule.c#L1584 if it only needed to pick from two vals it'd be a few lines with python boilerplate. You'd maybe be a bit quicker wiht a normal if check too since it doesn't need to do as much internally
timeit is so weird
that takes 1s per iteration
like which part is sleep(0.33) lol
In C, the numeric ops could be a lot faster without the ifs if the compiler didn't optimize it out for you, but python does a lot of things around them anyway so you're better of doing the if (or not caring about speed and using min/max anyway since it's python)
n here is the length of random numbers compared:
setup = lambda n: tuple([random.randrange(10**n) for j in range(2)])
after 4 min overtakes the weird thingie
Try doing normal if checks for the comparison instead of relying on just math
like, a third function return a if a<=b else b?
yeah something like that
But most of the runtime in really simple functions like that comes from the call itself
yikes
this is with:
perfplot.show(
setup = lambda n: [tuple([random.randrange(10**n) for j in range(2)]) for i in range(1000)],
kernels = [
lambda arr:[fs(*x) for x in arr],
lambda arr:[min(*x) for x in arr],
lambda arr:[x[0] if x[0]<=x[1] else x[1] for x in arr]
],
labels = ["fs","min","ifelse"],
n_range = [i for i in range(1,18)],
xlabel = "len(n)")
Took me a while to notice the green line that aspires to be the axis
better pic
(on the first, it looks as if it's 0, but that's just bad start of y axis)
still very low, though
hmm
I wonder where would numpy.min be 😛
I'd guess it's around the builtin, depending on what it's supposed to work with
You can see how much the function call (and name lookup) takes up here
In [127]: def f(): return 10 if 10<=20 else 20
In [128]: timeit f()
79.7 ns ± 0.151 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [129]: timeit 10 if 10<=20 else 20
34.5 ns ± 0.112 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Actually, not sure if it has to look up the name
huh
np.min is worse, actually
there's the 3 previous functions, and np_min on the whole array is the top
and np.min elementwise is, well...
perfplot.show(
setup = lambda n: [tuple([random.randrange(10**n) for j in range(2)]) for i in range(1000)],
kernels = [
lambda arr:[fs(*x) for x in arr],
lambda arr:[min(*x) for x in arr],
lambda arr:[x[0] if x[0]<=x[1] else x[1] for x in arr],
lambda arr:[np.min(x) for x in arr],
lambda arr:np.min(arr, axis=1)
],
labels = ["fs","min","ifelse","np.min elementwise","np.min(whole)"],
n_range = [i for i in range(1,18)],
xlabel = "len(n)")
How can I replace an object in memory?
context is I'm applying this hack
https://stackoverflow.com/a/57436077/3620725
but in some cases there are other libraries or iPython utilities referencing an existing QApplication instance which gets deleted and throws an error, so I'd like to replace the old QApplication instance with the new one in the same memory location
Found this but it's outdated and doesn't work for Python 3 https://stackoverflow.com/a/18234558/3620725
so that example uses gc but you could prob do it with ctypes
Binklederry, what kind of object?
It's not going to be stable and it will defenetely be undefined behaviour but might work with ctypes
@spring fractal @rugged sparrow The object is a PyQt5 application instance (PyQt5.QtWidgets.QApplication)
My scenario is that for whatever reason PyQt5 strictly does not allow QtWebEngineWidgets to be imported after a PyQt5 QApplication exists. The problem is that I cannot control this, because my package is meant for iPython EDA and might be imported after people already did Matplotlib plotting with a PyQt5 backend which would create a QApplication
So I have implemented this workaround based on this answer https://stackoverflow.com/a/57436077/3620725
try:
from PyQt5 import QtWebEngineWidgets
except ImportError as e:
if e.msg == "QtWebEngineWidgets must be imported before a QCoreApplication instance is created":
logger.info("Killing QtWidgets.QApplication to reimport QtWebEngineWidgets")
from PyQt5 import QtWidgets
app = QtWidgets.QApplication.instance()
if app is not None:
import sip
app.quit()
sip.delete(app)
import sys
from PyQt5 import QtCore, QtWebEngineWidgets
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
app = QtWidgets.QApplication(sys.argv)
else:
raise e
However, if a third-party module has saved a python reference to the old QApplication and then tries to use it, it will raise an error since I destroyed it - I'm trying to solve this problem possibly by replacing the object in memory or updating all references. That's what I'd like some help with.
maybe you can create a copy of the object with ctypes, do your import, then put it back
but then that would have to be version specific i guess
then put it back
@spring fractal
Is that possible? that's the part I was asking about, how can I replace it in memory so all old references point to the new copy?
you cant
thats not how pointers work
but you might be able to cheat it a little
by temporarily moving the object
what version of python are you intending to support
don't have any specific requirements, just as much as possible
I was thinking I could use gc.get_referrers and update the references to the new application but I can't find much documentation on it
from PyQt5 import QtWidgets
import gc
# Create QApplication
appref1 = QtWidgets.QApplication([])
# Get current QApplication instance
appref2 = QtWidgets.QApplication.instance()
appref3 = QtWidgets.QApplication.instance()
print(id(appref1))
print(id(appref2))
print(id(appref3))
print(len(gc.get_referrers(QtWidgets.QApplication.instance())))
Output
1500014600688
1500014600688
1500014600688
1
I expected that to print 3 not 1
Oh it returns a list of dicts.. hm. I can spend some time learning and trying that but wanted to see if that would even potentially work, or should I look at ctypes instead
oh wait i know,
import mmap
import ctypes
import sys
...
# allocate a new memory segment
what_you_needed_gone_true_size = sys.getsizeof(what_you_needed_gone)
location_of_what_you_needed_gone = id(what_you_needed_gone)
mm = mmap.mmap(-1, 1024)
for i in range(what_you_needed_gone_true_size):
mm.write(ctypes.c_char.from_address(location_of_what_you_needed_gone + i).value)
# do your stuff here
...
#write back the object
mm.seek(0)
for i in range(what_you_needed_gone_true_size):
ctypes.c_char.from_address(location_of_what_you_needed_gone + i).value=mm.read(1)
mm.close()
now i warn you
this is undefined behaviour as ****
basically make a new memory mapping, write object to that, do you stuff that you couldnt do, write it back to the same place afterwards
and i didnt test this so some stuff might be wrong
and be carefull with this because you can get remote shell trough ctypes lol
lol ok, this is a great starting point though I'll see what it does and try get it working for my case
How to do 1 liner for dictionary assignments?
a[x] = b[x] for x in c
like this? doesnt wrk
you can call the __setitem__ dunder directly, or take advantage of comprehensions like
[do_something_with_dict for some_dict[key] in [value_to_assign_to_key]]
what about
a.update({x: b[x] for x in c})
@proper vault I never thought about using comprehension like that
!e x = {} y = {} [0 for x[0],y[0] in [[1,2]]] print(x,y)
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
{0: 1} {0: 2}
!e
[ print(d,e)
for d in [{}]
for e in [[0,1]]
for d['a'] in [3]
for d['b'] in [5]
for d['a'] in [4]
for e[1] in [6]]
@proper vault :white_check_mark: Your eval job has completed with return code 0.
{'a': 4, 'b': 5} [0, 6]
in case := is too convenient
IO type from Haskell! Doesn't fit in here, sadly
https://repl.it/@int6h/iotype#main.py
It turns out that it's actually pretty fun
Nice!
I kinda want to see janky do-notation / monads in Python now lol.
Python has enough syntax stuff I wonder if you could actually try and shoehorn in a Coq or Idris like type system.
I would love to add do notation somehow
but it will be impossible to make it work with mypy, I suppose
https://paste.pythondiscord.com/bevebohadi.py
I made this and I am proud ^
class MemoryAttachmentStorage:
_attachments: AIORef[Dict[int, Attachment]]
_max_uid: AIORef[int]
@property
def attachments(self) -> AIO[Dict[int, Attachment]]:
...
@property
def increment_max_uid(self) -> AIO[None]:
...
def insert_attachment(self, att: Attachment) -> AIO[int]:
...
@property
def index(self) -> AIO[List[int]]:
...
@property
def max_uid(self) -> AIO[int]:
...
class MockAttachmentRepo:
storage: MemoryAttachmentStorage
def __init__(self):
self.storage = MemoryAttachmentStorage()
def load_attachment(self, uid: int) -> AIO[Maybe[Attachment]]:
m_atts = self.storage.attachments
return m_atts.fmap(lambda atts: Maybe.from_optional(atts.get(uid)))
def save_attachment(self, att: Attachment) -> AIO[Maybe[int]]:
return self.storage.insert_attachment(att).fmap(Maybe.just)
def index_attachments(self) -> AIO[Maybe[List[int]]]:
return self.storage.index.fmap(Maybe.just)
I think IORef (AIORef here, because it's asynchronous) is not that bad of an idea. Unlike traditional mutable state, it preserves identity of a value.
While the value inside a reference cell can change, 1) the value you get from AIORef.get_value() is immutable; 2) the attribute storing the cell (e.g. _max_uid) doesn't change -- it always refers to the same cell. As a bonus, it makes mutable state very explicit and allows you to monitor the change of a value
So you can do
score: AIORef[int] = AIORef(0, on_change = lambda pts: print_aio("Score is now:", pts))
print_score = score.get_value() >= (lambda pts: print_aio("Current score:", pts))
main2: AIO[None] = print_score >> score.change(lambda pts: pts + 1) >> print_score
main2.unsafe_perform_sync()
to get:
Current score: 0
Score is now: 1
Current score: 1
and every time score changes, you can log that change
so AIORef :: A -> (A -> AIO[None]) -> AIORef[A]
@formal sandal what is aiot here?
huh?
oh, the io name clashed with the built-in io module, so I renamed it to iot
and for consistency, I renamed aio to aiot
AIO is the asynchronous version of IO
The code is quite cluttered with typing garbage, maybe I could clean it
If I use Chinese characters in the naming of my variables, will I sooner or later run into problems?
If I remember correctly Python supports all unicode characters so it's possible
!e py 名称 = "TizzySaurus" print(名称)
@last locust :white_check_mark: Your eval job has completed with return code 0.
TizzySaurus
@last locust Thank you. I'll just use it for my tutorials then.
Well, not all unicode characters. Unicode letters, I think.
Even some non-letters it supports
@glossy thorn I don't think you should use unicode names outside of... well, this channel
A = 震耳欲聋:deafening B = 世外桃源 Shangri-La i = 比干示弱 not be outdone
震耳欲聋 = 12
世外桃源 = 3
print(震耳欲聋 + 世外桃源)
print(震耳欲聋 - 世外桃源)
print(震耳欲聋 * 世外桃源)
print(震耳欲聋 / 世外桃源)
print(震耳欲聋 // 世外桃源)
print(震耳欲聋 % 世外桃源)
print()
for 不甘示弱 in range (1, 震耳欲聋 // 世外桃源):
print(不甘示弱)
I mean, it ran.
(I just started... sorry)
!e ```py
A = 震耳欲聋:deafening B = 世外桃源 Shangri-La i = 比干示弱 not be outdone
震耳欲聋 = 12
世外桃源 = 3
print(震耳欲聋 + 世外桃源)
print(震耳欲聋 - 世外桃源)
print(震耳欲聋 * 世外桃源)
print(震耳欲聋 / 世外桃源)
print(震耳欲聋 // 世外桃源)
print(震耳欲聋 % 世外桃源)
print()
for 不甘示弱 in range (1, 震耳欲聋 // 世外桃源):
print(不甘示弱)
@last locust :white_check_mark: Your eval job has completed with return code 0.
001 | 15
002 | 9
003 | 36
004 | 4.0
005 | 4
006 | 0
007 |
008 | 1
009 | 2
010 | 3
!e py = 1 print()
@last locust :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | = 1
003 | ^
004 | SyntaxError: invalid character in identifier
Yea I guess not all unicode
Lucky~
@glossy thorn
Names are always written in English for several reasons:
- other programmers are usually familiar with English, so they will be able to understand your code
- it's consistent with built-in names
- it works with all fonts
- not all languages even support unicode names
!e
Fаlse = True
Truе = False
print(Truе, Fаlse)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
False True
I have yet to see any advantage in using unicode names
Yeah, it's certainly slower. But, I need to learn like 4000 Chinese idioms if I want to take the Chinese civil service exam. So using said idioms as names for my variables is like killing two birds with one stone. @formal sandal
I have yet to see any advantage in using unicode names
@formal sandalobfuscationlol
Also, I keep using the wrong parantheses () as opposed to ()
👀
stop giving me evil ideas for a programming language
How many different unicode parentheses are there?
But, only one works for python. Right?
python is (){}[] only. If you want fancy unicode brackets, use raku
by the way, [](){} is valid C++
it's a no-op lambda
and [](){}() is how you call it
Are you use {} works...?
they didnt mean all work everywhere.
(), {}, [] have different meaning
Ahh... of course. How silly of me.
but all of them are used in some context
some languages obnoxiously treat < and > as braces as well
All are used in multiple contexts tbf
yep
yep
So yea all multiple uses
{} = set/dictionary
[] = list/indexing
() = calling function/for mathematical order etc.
{} being for both a set and a dict is an unfortunate state of being.
because {} is an empty dict, not an empty set.
technically, it's possible to implement a dict as a set
I did that when I made my own set and hashmap in C
You can store (K, V) pairs, and the hash function is (K, V) -> hash(K)
and equality function is (K1, V1), (K2, V2) -> K1 == K2
() [] {} ༺༻ ༼༽ ᚛᚜ ⁅⁆ ⁽⁾ ₍₎ 〈〉 ❨❩ ❪❫ ❬❭ ❮❯ ❰❱ ❲❳ ❴❵ ⟅⟆ ⟦⟧ ⟨⟩ ⟪⟫ ⦃⦄ ⦅⦆ ⦇⦈ ⦉⦊ ⦋⦌ ⦑⦒ ⦓⦔ ⦕⦖ ⦗⦘ ⧘⧙ ⧚⧛ ⧼⧽ 〈〉 《》 「」 『』 【】 〔〕 〖〗 〘〙 〚〛 〝〞 ︗︘ ︵︶ ︷︸ ︹︺ ︻︼ ︽︾ ︿﹀ ﹁﹂ ﹃﹄ ﹇﹈ ﹙﹚ ﹛﹜ ﹝﹞ () [] {} ⦅⦆ 「」 ⸨⸩ these are all the pairs raku supports. pretty wack.
Raku... It's not a very popular programming language is it? When I type "Raku what is it used for?" I get Japanese pottery.
Meanwhile, I have found the resonant frequency of my skull...
gotta stop procrastinating
It has been renamed from perl6 pretty recently, so google kind of sucks at finding things about it. Give it time to reindex things
@formal sandal What you could do is start 3 projects and just switch between them... like you use project A to procrastinate on project B, project B to ... etc.
Well, I have to finish some stuff for tomorrow
I know what you're talking about, though.
Perl isn't that what old cartridge games were made with?
I developed an entire programming language to ease creating web forms for the Insights project
Perl isn't that what old cartridge games were made with?
nvm
Perl is generally used as a scripting language. It tends to be a write once, never read again language. Raku is a bit better, but still looks like symbol soup. But you get custom operators (as in you can make obj᚛some values᚜ call your own function) and syntax.
stop giving me evil ideas for a programming language
@formal sandal
https://github.com/reinderien/mimic
):
@full kestrel i found gc.get_referres, it might be more specific to what you are looking for. https://docs.python.org/2/library/gc.html#gc.get_referrers
Suppose I have a nested function like this:
def f():
def g():
def h():
...
return h
return g
What would be the best way to make a decorator that allows it to be written as this?:
@nested
def f():
def g():
def h():
...
I think ast could be used, but that's a nightmare, right?
Another cool feature would be:
@nested
def f():
def g():
@some_decorator
def h():
...
(it should preserve decorators)
For example, I have a few functions that look like this:
def insert_one(record: Entry) -> Callable[[Collection], AIO[ObjectId]]:
def _insert(coll):
async def resolve():
result: InsertOneResult = await coll.insert_one(record)
return Either.right(result.inserted_id)
return AIO(resolve)
return _insert
and they would look much nicer with this syntax:
@nested
def insert_one(record: Entry) -> Callable[[Collection], AIO[ObjectId]]:
def _insert(coll):
@AIO
async def resolve():
result: InsertOneResult = await coll.insert_one(record)
return Either.right(result.inserted_id)
it seems possible, you can inspect the code object to of the outer function get the code object of the function defined within, which you can trivially construct into a function.
And I'd have to somehow decide whether there is a decorator or not.
Well, that's not too hard.
As a last resort, I could use inspect.getsource
I also want it to somehow work with mypy... I guess, the type of nested should be def (T) -> T, and I just put # type: ignore in the definition
The IO type actually is a viable idea, it seems. https://paste.pythondiscord.com/afawayavom.py
@full kestrel i found gc.get_referres, it might be more specific to what you are looking for. https://docs.python.org/2/library/gc.html#gc.get_referrers
@spring fractal Hey thanks! I was looking at the method and it does get me references but doesnt give an easy way to redirect them to my new instance.
But anyways I actually found an alternative solution to my initial problem (managed to reinitialize the original object after fake-deleting it, instead of actually deleting it then rewriting a new instance to its old location like we discussed)
well alright, personally i feel like screwing with python internals is more fun though 😛
lol yeah probably for everyone that regulars #esoteric-python
oh damn i just came up with a project idea, i wonder if it would be possible to make a library that makes custom operators possible
like adding output << string; type syntax
But isnt that already built into python with dunder methods https://docs.python.org/3/library/operator.html#operator.__ilshift__
@spring fractal look up forbiddenfruit
see the example at the bottom
ohh that's hot
i think it only works for a specific minor version, like 3.6 or 3.7
haha nice
So, um, I created a horrible language, and it's turing complete, apparently.
It was initially intended to make web forms with checkboxes and radio buttons, but I added a tiny bit of esoteric stuff.
I can prove that it's Turing complete because I can use it to express SKI calculus:
https://repl.it/@int6h/FormDSL#turing_complete.rb
This is the tutorial (with descriptions of all built-in functions):
https://gist.github.com/decorator-factory/7c0fa628f715e141e5ba4d9c9ae51eb8
It is purely functional, except for the meta and debug functions (they don't introduce mutable state, though)
For example, this is how the S combinator is defined:
# (run (run (run <S> x) y) z) = (run (run x z) (run y z))
% <S> &({(vec) (<+ &(<.S.1>)) (<+ .>.) (unvec$)})
# x y -> &(<.S/2> x y)
% <.S.1> {(vec) (<+ &(<.S.2>)) (<+ .>.) (unvec$)}
# x y z -> (run (run x z) (run y z))
% <.S.2> {(vec) (<-$-> [<run-x-z> <run-y-z>]) (<+ run) (unvec$)}
# [x y z] -> (run x z)
% <run-x-z> {(<-$-> [v.. ..v]) (<+ run) (unvec$)}
# [x y z] -> (run y z)
% <run-y-z> {(<-$-> [.v. ..v]) (<+ run) (unvec$)}
<> around the names are purely aesthetic, names are (?![-A-Z0-9])[-a-zA-Z0-9_><+=*^.|\/$]+
so ./+/= is fair game for names?
./+/=?
yep
You can look at the built-in names here:
https://gist.github.com/decorator-factory/7c0fa628f715e141e5ba4d9c9ae51eb8#built-in-functions
the implementation actually uses .>>^., <-$-> and some others
<-$-> accepts some value x and a vector (list) of functions. (<-$-> x [f g h...]) ~ [(f x) (g x) (h x) ...]
it's like map, but in reverse
The language supports quoted values. A quoted value is an unevaluated expression. So (join "a" "b" "c") is a function call that evaluates to "abc", and &(join "a" "b" "c") is a quoted expression which is stored literally.
.>>^. takes a vector of values (e.g. [a b c]) and a quoted function call (e.g. &(f x y)) and inserts the values as additional arguments (&(f x y a b c)).
Just like in SKI calculus, there are no local variables.
This is the most challenging side of the language, and that's why all the crazy functions are used.
Surely there's a way to bind names to values that programs could use in place of proper variables?
Well, you can only define constants.
But you could create some kind of monstrous macro.
I was going to try that
There are key-value maps, so binding names to values is possible.
And there's also a very complex undocumented mechanism which I was planning to document.
okay
I'm struggling to understand the rules on when I can modify an instance's class. Anyone have recommended reading or an explanation on this?
from collections import OrderedDict, UserDict
class SubUserDict(UserDict):
def __init__(self):
super().__init__()
class SubOrderedDict(OrderedDict):
def __init__(self):
super().__init__()
user = UserDict({'a': 1, 'b': 2, 'c': 3})
ordered = OrderedDict({'a': 1, 'b': 2, 'c': 3})
# This works
user.__class__ = SubUserDict
# This fails
user.__class__ = dict
# This fails
ordered.__class__ = SubOrderedDict
TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
It seems like this is error CPython specific? Is there no way to cast an instance to a subclass inplace that isn't implementation specific. My motivation here is I'm trying to monkeypatch some dundermethods of an instance without affecting all other instances of the same class
Why don't you just make a new instance of child class with the data from the object
Never do this in production.
Why don't you just make a new instance of child class with the data from the object
@modest glade
Because I don't make it. My specific scenario is I have a package where the user passes in a pandas DataFrame to my GUI and I want to be able to print a message every time this DataFrame gets modified (by overriding some dunder methods) including when the user modified it from iPython so creating a new identical instance would not work
I think you could just directly assign to the methods
couldnt you just do a while loop
Since they are just objects in python
it's bad practice, but i think it will work
I think you could just directly assign to the methods
@modest glade that's what I tried but learned you cant override dunder methods on an instance, only on the class
Why can't you just make the object an instance of the subclass to begin with
he dosent have control
^
i was thinking about just doing a while loop, constantly checking if the values are changed
its really bad practice
but it may work
oh man that would be dirty lol, I hope it doesn't come to that
yeah would have to be
@full kestrel I think I figured it out
class Test:
def __len__(self):
return 1
def len(self):
return 2
obj = Test()
functype = type(obj.__len__)
obj.__len__ = functype(len.__code__, obj.__dict__)
print(len(obj))
seems like it varies by version of python tho
sometimes it wants len.__code__ sometimes it wants just len
POC in #bot-commands tho
actually doesn't work, it patches the whole class
oh ok, it also seems to fail on OrderedDict but not UserDict like my initial code above, but a different error
from collections import OrderedDict, UserDict
user = UserDict({'a': 1, 'b': 2, 'c': 3})
ordered = OrderedDict({'a': 1, 'b': 2, 'c': 3})
def len(self):
return 2
# SUCCEEDS
functype = type(user.__len__)
user.__len__ = functype(len, user.__dict__)
print(len(user))
# FAILS
functype = type(ordered.__len__)
ordered.__len__ = functype(len, ordered.__dict__)
print(len(ordered))
Anyways, it seems like Pandas dataframes do work with my first code (even though some classes like OrderedDict do fail which I was trying to understand). So now I'm back on track
A fine alternative to while loops checking for changes is always sys.settrace.
guys i finally learned how to Hello World in python after months of trying
(lambda _, __, ___, ____, _____, ______, _______, ________: getattr(__import__(True.__class__.__name__[_] + [].__class__.__name__[__]), ().__class__.__eq__.__class__.__name__[:__] + ().__iter__().__class__.__name__[_____:________])(_, (lambda _, __, ___: _(_, __, ___))(lambda _, __, ___: chr(___ % __) + _(_, __, ___ // __) if ___ else (lambda: _).func_code.co_lnotab, _ << ________, (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __) - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) << ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) << __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______ << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) + _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ << _))) + (_____ << ______) + (_ << ___))))(*(lambda _, __, ___: _(_, __, ___))((lambda _, __, ___: [__(___[(lambda: _).func_code.co_nlocals])] + _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []), lambda _: _.func_code.co_argcount, (lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))
Finally works !
soooo proud of you!
!e
(lambda _, __, ___, ____, _____, ______, _______, ________: getattr(__import__(True.__class__.__name__[_] + [].__class__.__name__[__]), ().__class__.__eq__.__class__.__name__[:__] + ().__iter__().__class__.__name__[_____:________])(_, (lambda _, __, ___: _(_, __, ___))(lambda _, __, ___: chr(___ % __) + _(_, __, ___ // __) if ___ else (lambda: _).func_code.co_lnotab, _ << ________, (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __) - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) << ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) << __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______ << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) + _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ << _))) + (_____ << ______) + (_ << ___))))(*(lambda _, __, ___: _(_, __, ___))((lambda _, __, ___: [__(___[(lambda: _).func_code.co_nlocals])] + _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []), lambda _: _.func_code.co_argcount, (lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))
@fiery hare :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 1, in <lambda>
004 | File "<string>", line 1, in <lambda>
005 | AttributeError: 'function' object has no attribute 'func_code'
b r u h
what
didnt work
false advertisement
lol
also you just learned about dunders and you're already ready to dive into code gore?
nOPE
also you just learned about dunders and you're already ready to dive into code gore?
just started beginning to understand them lol
Also salt-die can there be function composition?
yeah, it's not too much work
I didn't think it had a real use case but this morning I did pmb = lambda x: pprint(mb(x))
you have to be careful not to mix up arities
because I needed to wrap my function in pprint quickly during a live code thing I was doing
i don't know if i have my previous snippet saved on it, i can reconstruct though
In [17]: class Func:
...: def __init__(self, func):
...: self.func = func
...: def __mul__(self, other):
...: return lambda *args: self.func(other(*args))
...: def __call__(self, *args):
...: return self.func(*args)
...:
In [18]: f = Func(lambda x: 2 * x)
...: g = Func(lambda x: x + 5)
...: (f * g)(8)
Out[18]: 26
did i do it in the right order
would look cleaner with a Var class as well
hmm
something like sympy's symbol:
In [19]: from sympy import Symbol
In [20]: x = Symbol('x')
In [21]: f = 2 * x + 2
In [22]: f
Out[22]: 2*x + 2
could give you cleaner composition
the order differs from definition to definition AFAIK
i think sympy symbols build actual parse trees, would be a fun exercise to implement
that is, with __mul__ and other numeric operations
Well, it is way easier than typical expression parsing since operator precedence will be done by CPython
you know, i was browsing through their source and they had decorators for operator precedence anyway
i didn't follow the logic all the way through though
No it is defined by the grammar
Hold on
expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom_expr ['**' factor]
atom_expr: ...```
This create operator precedence, according to the dragon book, the book GvR followed to create the parser and that I'm trying to understand
no, i mean for sympy
not the python grammar
example:
@sympify_return([('other', 'Expr')], NotImplemented)
@call_highest_priority('__radd__')
def __add__(self, other):
return Add(self, other)
@sympify_return([('other', 'Expr')], NotImplemented)
@call_highest_priority('__add__')
def __radd__(self, other):
return Add(other, self)
@sympify_return([('other', 'Expr')], NotImplemented)
@call_highest_priority('__rsub__')
def __sub__(self, other):
return Add(self, -other)
@sympify_return([('other', 'Expr')], NotImplemented)
@call_highest_priority('__sub__')
def __rsub__(self, other):
return Add(other, -self)
@sympify_return([('other', 'Expr')], NotImplemented)
@call_highest_priority('__rmul__')
def __mul__(self, other):
return Mul(self, other)
@sympify_return([('other', 'Expr')], NotImplemented)
@call_highest_priority('__mul__')
def __rmul__(self, other):
return Mul(other, self)
i didn't look around long enough to unravel it
maybe later
sly has a simple way of defining precedence too
start of logic parser:
class LogicParser(Parser):
tokens = LogicLexer.tokens
precedence = (
('left', XOR, OR, IFF, IMPLIES),
('left', AND),
('left', '(', ')'),
('right', '~')
)
lookup = {
'xor': Xor,
'or': Or,
'<->': Iff,
'->': Implies,
'and': And
}
This could be production code for initialising an object's configuration, including user accounts, a database and a server.
well, cfg -> config, srv -> server
what is __pop_section?
whe biggest problems here are nested control flow and cryptic variable names
That function does too much and mixes levels of operation
If you can't get the creator to rewrite it, at least demand comments.
👍
what a douchebag
his oneliners aren't even inventive or cool
I can even read them
he is using list comprehensions where generator comprehensions could be used
Yea if you're gonna write a one liner it at least needs to be unreadable /s
an init should never be that long good lord
@zenith hare hit your coworker over the head with a medium sized mallet plz lol
thats the kinda stuff that gives python a really really bad name
how old is this guy
I have my dms turned off on here, way to many people dm me other wise, Dw about it lol. I’m pretty sure ik his type
Wow, pyright is so much better at type inference than mypy, and it can even reason about my pretty type-maze code
Given that fetch_one : Cursor -> AIO[Maybe[tuple]] and first : Tuple[T, ...] -> T and Maybe.lift : (A -> B) -> (Maybe[A] -> Maybe[B]), it managed to deduce from
def fetch_single(sql: str, arg: SqlParam = ()):
"""Make a query that produces a single result and return
a single value instead of a one-element tuple"""
def _(cur: aiopg.Cursor):
return fetch_one(sql, arg)(cur) * Maybe.lift(first)
return _
that fetch_single : (sql: str, arg: SqlParam = ()) -> (cur: Cursor) -> AIO[Maybe[T]]
and if you make a mistake, it tells you its deduction path and what exactly is wrong, unlike mypy which just says "you're wrong" or something
imagine
class A:
__class_getitem__ = print
A["lol"]
contrast it with
def my_print(*args):
print(*args)
class A:
__class_getitem__ = my_print
A["lol"]
so
A = TypeVar("A")
N = TypeVar("N", bound="Nat")
class Zero: pass
class Succ(Generic[N]):
def __init__(self, v: N): pass
Nat = Union[Zero, Succ["Nat"]]
class VectorType(Generic[A, N]):
def __init__(self: "VectorType[A, Zero]", value=None, rest=None):
"""Pretty please don't call this directly"""
self.value = value
self.rest = rest
def __eq__(self, other: "VectorType[A, N]") -> bool:
if self.value != other.value:
return False
return self.rest == other.rest
nil: VectorType[A, Zero] = VectorType()
def cons(value: A, vec: VectorType[A, N]) -> VectorType[A, Succ[N]]:
return VectorType(value, vec)
def eq(a: VectorType[A, N], b: VectorType[A, N]) -> bool:
return a == b
If
x = cons(1, cons(2, cons(3, nil)))
y = cons(1, cons(5, cons(3, nil)))
z = cons(1, cons(2, nil))
then eq(x, y) typechecks, and eq(x, z) doesn't
nice
dependent typing-ish?
yeah
I don't think it's possible to do addition...
Maybe with @overload?
no, I don't think it's possible
I really started to like phantom type shenanigans in Python
I have found the solution
https://paste.pythondiscord.com/sogenanifu.py
Hell yeah, it works! 3+3=6
I'm sure nobody needs a vector with more than 32 elements
Is nil meant to compare not equal to everything?
I might be tired, but if nil has self.rest = None, then in the __eq__ it should return False.
Even for nil == nil.
That doesn't seem like intended behaviour.
Actually, that means all lists compare inequal since the comparisons are recursive
Unless they explicitly specify a non-None rest at some point, like 0.
rest should always be a VectorType, as we are working with linked lists
I don't see that in the type hints, especially given it can be None.
Yeah, I screwed up
fixed now
rest is VectorType unless it's nil, in which case it's None
Username checks out.
def fib(n):
return max(
d['b']
for d in [{}]
for d['a'], d['b'] in [(0, 1)]
for _ in range(n)
for d['a'], d['b'] in [[d['b'], d['a'] + d['b']]]
)
``` this is pretty cool
There's a word for things that are terrifying yet beautiful: that code is 'sublime'.
for d['a'], d['b'] in [(0, 1)]
yikes, didn't know you could mutate dicts with iteration like that
everything you can assign to you can put into a for loop or a comp
import random, functools.partial
# cause regret
for c in object.__subclasses__():
try:
oldeq = c.__eq__
def __eq__(self, other):
return random.random() < 0.001 or oldeq(self, other)
c.__eq__ = __eq__
except TypeError:
pass
@proper vault where did you get that wild fib function? I'd like to put it in a tweet 🙂
I made it
do not mind, don't bother crediting
thanks 🙂
!e
def accumulate(f, x, iterable):
return [
r
for r in (
acc[0]
for acc in [[x]]
for a in iterable
for acc[0] in [f(acc[0], a)]
)
]
print(accumulate(lambda a, b: a + b, 0, [1, 2, 3, 4, 5]))
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
[1, 3, 6, 10, 15]
actually, this would be neater like
def fib(n):
return max(
d.b
for d in [fib]
for d.a, d.b in [(0, 1)]
for _ in range(n)
for d.a, d.b in [[d.b, d.a + d.b]]
)
also uses one more esoteric python feature
which is always a good thing
inf = (1 for i in [iter([1])] for v in i for x in [i.__setstate__(0)])```
infinite generator
Whoa, that fib function is crazy cool
is nobody going to comment on my even-more-hacky infinite generator :(
[i.__setstate__(0)]
that moves the list_iterator object back so that it ends up being infinite
is __setstate__ specific to list iterators
cool
!e
def printlen(x): print(len(x))
def argslist(x): return list(x.args)
def add(value_error, arg): raise Exception(*value_error, *arg)
def fibonacci(a, b, x):
try:
assert b<x
printlen(b)
try:
add(a,b)
except Exception as e:
fibonacci(argslist(e), a, x)
except AssertionError as e:
print(e)
threshold = 1000
fibonacci([[]],[[]],[[]]*threshold)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | 1
002 | 1
003 | 2
004 | 3
005 | 5
006 | 8
007 | 13
008 | 21
009 | 34
010 | 55
011 | 89
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ekosopuhuf
this is just gross
If you remove assert b<x, it eats all your memory without any exception
!e
print("test")
@gaunt rivet :white_check_mark: Your eval job has completed with return code 0.
test
@gaunt rivet :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | NameError: name 'blablabla' is not defined
Lol
@gaunt rivet please do that in #bot-commands
Oops

What's the deal with lists and tuples not being equal? i.e. [1,2,3] != (1,2,3)
Because python is strongly typed
@drowsy pine because the content may be equal, but the container (tuple or list) is not
Pretty much ^^. You can use something like len(a)==len(b) and all(x==y for x,y in zip(a,b)) to compare the contents. Don't think there's a faster way
also, that's hardly #esoteric-python, now that I think of it; unless you have something very cursed in mind 😛
Some types have a custom__eq__ that allows for == to have variable behavior depending on the types it is being used against
These are all builtins, of different types comparing equal
except list and tuple don't get along
range(3) != [0, 1, 2]
Ok maybe that's just Python 2
well, yeah, because range returned a list
So float and int get along.. Unicode and bytestring and bytearrays all get along
I'm still stuck in Python2
why?
However Python3 bytearray(b"abc") == b"abc"
Mutable and immutable.. getting along
In Python3 u"abc" != b"abc" but in Python2 it is.. Makes no sense
Because a bytestring has no encoding.
I don't follow.. what does encoding have to do with anything?
https://stackoverflow.com/questions/30580386/why-does-comparison-of-bytes-with-str-fails-in-python3
if you live in a happy ASCII world, yes, everything is fine
I would expect if b"abc" == bytearray(b"abc") then it should follow that (1,2,3) == [1,2,3]
https://docs.python.org/3.0/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit
Python 3.0 uses the concepts of text and (binary) data instead of Unicode strings and 8-bit strings. All text is Unicode; however encoded Unicode is represented as binary data. The type used to hold text is str, the type used to hold data is bytes. The biggest difference with the 2.x situation is that any attempt to mix text and data in Python 3.0 raises TypeError, whereas if you were to mix Unicode and 8-bit strings in Python 2.x, it would work if the 8-bit string happened to contain only 7-bit (ASCII) bytes, but you would get UnicodeDecodeError if it contained non-ASCII values. This value-specific behavior has caused numerous sad faces over the years.
a tuple isn't an immutable list, it has different semantics
bytes isn't an immutable bytearray either
bytes is an immutable sequence of bytes. bytearray is a mutable sequence of bytes.
list is a collection of varying-length, usually homogenous data (like [1, 2, 3, 4]). tuple is a collection of usually heterogenous data, usually with a fixed or a limited size (not just in Python, in languages that have tuples).
Like namedtuple.
It looks like bytes aren't equal to their equivalent lists of numbers.
docs:
Lists
Lists are mutable sequences, typically used to store collections of homogeneous items (where the precise degree of similarity will vary by application).
Tuples
Tuples are immutable sequences, typically used to store collections of heterogeneous data (such as the 2-tuples produced by the enumerate() built-in). Tuples are also used for cases where an immutable sequence of homogeneous data is needed (such as allowing storage in a set or dict instance).
Bytearray Objects
bytearray objects are a mutable counterpart to bytes objects.
anyway, it's not such an important issue
Still not quite clear. [1, 'a', None] == [1, 'a', None] != (1, 'a', None)
I just don't know why they would chose to go that route with the language
I guess Python3 is a little more consistent with unicode not being the same as bytes
A list is not a tuple, I suppose. But apparently a number is a number.
to be honest, it's quite awkward to compare an int and a float...
I don't know where it would be useful
Maybe checking if x / 2 == x // 2.
Checking if x is an exact integer value is better as x == int(x) than as x = float(int(x)).
Maybe checking if x / 2 == x // 2.
if x%2==0?
int and float is weird with {1: "one", 1.0: "one"} evaluating to {1: 'one'}
Or actually maybe that's a good thing
keys that are equal (==) are, well, equal
hey how can I change the browser which my bot opens???
@formal sandal the point of int float complex bool Fraction Decimal all comparing equal when they are equal is so that I can use an int in a complex computation and have it get the correct result, rather than possibly rounding/comparing incorrectly like in other languages
hm
Well, casting an int to a complex is ok, but backwards is not really... But I don't know if it's possible to distinguish
They are the same mathematically which is a big part of python's use
And being able to use the various types inbetween without much hassle can improve that further
Why does something as "simple" as this cause a memoryError?..
In [18]: eval(" ".join(["not"]*10000) + " True")
s_push: parser stack overflow
---------------------------------------------------------------------------
MemoryError Traceback (most recent call last)
<ipython-input-18-66a8514f135e> in <module>
----> 1 eval(" ".join(["not"]*10000) + " True")
MemoryError:
Probably the same reason as the below.
!e ```py
import ast
ast.literal_eval("("*300+"),"*300)
@earnest wing :x: Your eval job has completed with return code 1.
001 | s_push: parser stack overflow
002 | Traceback (most recent call last):
003 | File "<string>", line 2, in <module>
004 | File "/usr/local/lib/python3.8/ast.py", line 59, in literal_eval
005 | node_or_string = parse(node_or_string, mode='eval')
006 | File "/usr/local/lib/python3.8/ast.py", line 47, in parse
007 | return compile(source, filename, mode, flags,
008 | MemoryError
Too big of a literal.
it also seems that even stuff like chained nots can't be simplified:
el=eval("lambda x: "+" ".join(["not"]*1000) + " x")
In [29]: %timeit el(False)
6.99 чs + 68.4 ns per loop (mean + std. dev. of 7 runs, 100000 loops each)
In [30]: el2 = lambda x: x
In [31]: %timeit el2(False)
99.3 ns + 0.904 ns per loop (mean + std. dev. of 7 runs, 10000000 loops each)
>>> x = 1
>>> x
1
>>> not not x
True```
can you override nots, or is not always {True: False, False: True}[bool(obj)]
sure, but that should at least be equal and simplifiable to bool(x), or something similar.
...though you could potentially have an object that returns another object of its own class on __bool__... then applying bool can be done more than once with different results.
object.bool(self)
Called to implement truth value testing and the built-in operation bool(); should return False or True.
"Should". Riiiight 😛
I think __bool__() is required to return a bool, though that may just have been my linter.
!e ```py
class C:
def bool(self):
return "wahoo"
print(bool(C()))
@earnest wing :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 4, in <module>
003 | TypeError: __bool__ should return bool, returned str
bool is enforced
Ctypes, etc. might choose to ignore this.
oh, nice
but then applying a not to a non-bool is equivalent to not bool(x), which is always a bool, no strings attached. The subsequent logical operations on the result can therefore be simplified.
In theory, (considering bool subclasses are also enforced), a not not should always reduce. But that's probably not something a general parser considers /shrug
You're not going to be parsing lists that long anywhere so it's pretty much a non issue, you can also try the new parser
luckily, pypy doesn't raise a memoryerror on very nested structures
!e ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
@stark fable :x: Your eval job has completed with return code 1.
001 | s_push: parser stack overflow
002 | MemoryError
it is a type hint. They are not enforced in any way, you can think of them as comments of sorts
>>> def idk() -> str:
return 69
...
>>> idk()
69
>>> idk.__annotations__
{'return': <class 'str'>}
Well, you can use a type checker like mypy that will beat you up for that.
Or you can use some other tool to validate the arguments and the return type, or even create overloaded functions.
!e
from functools import wraps
def check_return_value(fn):
return_type = fn.__annotations__["return"]
if return_type is None:
return_type = type(None)
@wraps(fn)
def _(*args, **kwargs):
result = fn(*args, **kwargs)
if not isinstance(result, return_type):
raise TypeError(f"{fn.__qualname__} should have returned {return_type.__qualname__}, "
f"got {result}::{type(result).__qualname__}")
return result
return _
@check_return_value
def f() -> int:
return 42
@check_return_value
def g() -> str:
return 69
print(f())
print(g())
@formal sandal :x: Your eval job has completed with return code 1.
001 | 42
002 | Traceback (most recent call last):
003 | File "<string>", line 25, in <module>
004 | File "<string>", line 11, in _
005 | TypeError: g should have returned str, got 69::int
nice
what's the difference between __qualname__ and __name__ though?
what's the difference between
__qualname__and__name__though?
@tribal moon esoteric English, the though is unnecessary and incorrect
what's the difference between __qualname__ and __name__
The former has a qualified name
Qualified means it's prefixed by the names of the modules and classes is in
!e ```py
(lambda , , , ____, , , ______, ________: getattr(import(True.class.name[] + [].class.name[]), ().class.eq.class.name[:] + ().iter().class.name[:_])(, (lambda _, __, ___: (, __, ___))(lambda _, __, : chr( % __) + (, __, ___ // __) if ___ else (lambda: _).func_code.co_lnotab, _ << ___, ((( << __) + ) << (( << ____) - )) + ((((( << ) - ) << ) + ) << (( << ) + ( << ))) + ((( << _) - ) << ((((( << ) + )) << ) + ( << ))) + ((( << ) + ) << (( << ) + )) + ((( << ) - ) << (( << ))) + ((( << ) - ) << (((( << ) + ) << ) - )) - ( << (((( << ) - ) << ) + )) + ( << ((((( << ___) + _)) << _))) - (((((( << ) + )) << ) + ) << (((( << ) + ) << ))) + ((( << ) - ) << ((((( << ) + )) << ))) + ((( << ) + ) << (( << ))) + ( << _____) + ( << ___))))(*(lambda _, __, ___: (, __, ___))((lambda _, , : [([(lambda: _).func_code.co_nlocals])] + (, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []), lambda _: _.func_code.co_argcount, (lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))
@grand tree :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 1, in <lambda>
004 | File "<string>", line 1, in <lambda>
005 | AttributeError: 'function' object has no attribute 'func_code'
F
__code__
os has no attribute we_it
getattr(__import__(True.__class__.__name__[_] + [].__class__.__name__[__]), ().__class__.__eq__.__class__.__name__[:__] + ().__iter__().__class__.__name__[_____:________]) this is where the error is
().__class__.__eq__.__class__.__name__[:__] + ().__iter__().__class__.__name__[_____:________] is wr_it
because __ means 1 and _____ means 4 and _________ means 8
!e
print(().__class__.__eq__.__class__.__name__[:1] + ().__iter__().__class__.__name__[4:7])```
@tribal moon :white_check_mark: Your eval job has completed with return code 0.
we_it
!e
(lambda _, __, ___, ____, _____, ______, _______, ________: getattr(__import__(True.__class__.__name__[_] + [].__class__.__name__[__]), ().__class__.__eq__.__class__.__name__[:__] + ().__iter__().__class__.__name__[_____:________])(_, (lambda _, __, ___: _(_, __, ___))(lambda _, __, ___: chr(___ % __) + _(_, __, ___ // __) if ___ else (lambda: _).__code__.co_lnotab, _ << ________, (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __) - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) << ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) << __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______ << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) + _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ << _))) + (_____ << ______) + (_ << ___))))(*(lambda _, __, ___: _(_, __, ___))((lambda _, __, ___: [__(___[(lambda: _).__code__.co_nlocals])] + _(_, __, ___[(lambda _: _).__code__.co_nlocals:]) if ___ else []), lambda _: _.__code__.co_argcount, (lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))```
@tribal moon :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 1, in <lambda>
004 | AttributeError: module 'os' has no attribute 'wr_it'
Looks like except clauses are checked one after the other, like a switch case statement. It makes you think, couldn't you implement rudimentary pattern matching using try/except blocks?
3hat
you can but no fall thru
there is no fall through in pattern matching tho
also fwiw, switch cases don't have to be checked sequentially
in fact, they will often be optimized down to a jump table, making them faster than if forests
(referring to actual switch cases à la C)
hmm
ohhh
!e ```py
cache = {}
def switch(val):
cache[val] = type('',(Exception,),{'val':val})
raise cache[val]
def case(val=None,default=False):
if default:
return Exception
return cache.get(val,RuntimeError)
def test(val):
try:
switch(val)
except case(('a','b','c')):
print('abc')
except case((1,2,3)):
print('123')
except case(default=True):
print('default')
test((1,2,3))
test(('a','b','c'))
test(5)```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | 123
002 | abc
003 | default
@snow beacon ^
That looks fun and not unusable for production code, which are often mutually exclusive in this channel.
just need to ensure that switch raises the same exception class that case grabs
could do a lot with it
and you can't do pattern-matching like (a, b)
That would probably require settrace magic or function body rewriting or similar to get working. A switch statement is a fine achievement besides.
let's just wait for the mess that PM will be in 3.10
Maybe you could do
try:
switch(x)
except case( (0, str) ) as e:
_, label = e
print("OK:", label)
except case( (int, str) ) as e:
number, label = e
print(f"Error {int}:", label)
!e
!eval [code]
Can also use: e
*Run Python code and get the results.
This command supports multiple lines of code, including code wrapped inside a formatted code
block. Code can be re-evaluated by editing the original message within 10 seconds and
clicking the reaction that subsequently appears.
We've done our best to make this sandboxed, but do let us know if you manage to find an
issue with it!*
I was amused by this gem: https://github.com/pypa/setuptools/blob/55bfb7d86ed09c06db5c40eb2fae37975e2672e6/setuptools/package_index.py#L90
!e
(
(
lambda __, ___, ____, _____: getattr(
__builtins__,
().__class__.__name__[__ << __]
+ ().__iter__().__class__.__name__[(__).__rmul__(-1)]
+ [].__class__.__name__[____ % ___]
+ chr(_____)
+ ().__class__.__name__[__ >> __],
)
)(
(lambda _: _).__code__.co_nlocals,
(lambda _, __: _ | __).__code__.co_nlocals,
(lambda _, __, ___: _ | __ | ___).__code__.co_nlocals,
(
(lambda _, __, ___: _ & __ & ___).__code__.co_nlocals.__rmul__(
(lambda _, __, ___: _ | __ | ___).__code__.co_nlocals
)
+ (True.__rmul__((lambda _, __: _ | __).__code__.co_nlocals))
).__rmul__(
(
lambda _, __, ___, ____, _____, ______, _______, ________, _________, __________:
_
).__code__.co_nlocals
),
)
)(
(
lambda __, ___, ____, _____, ______: hex.__class__.__name__[
___.__rmul__(____ * _____) - ______
].upper()
+ hex.__class__.__name__[___.__rmul__(____ * _____) - _____ - ______]
+ hex.__class__.__name__[___] * 2
+ hex.__class__.__name__[___.__rmul__(____ * _____)]
+ chr(__.__rmul__(___) + _____)
+ Warning.__qualname__[______ - True]
+ hex.__class__.__name__[___.__rmul__(____ * _____)]
+ Warning.__qualname__[_____]
+ ().__class__.__name__[___]
+ {}.__class__.__name__[______ - True]
+ chr(__.__rmul__(___) + ___)
)(
(
lambda _, __, ___, ____, _____, ______, _______, ________, _________, __________: (
_
)
).__code__.co_nlocals,
(lambda _, __, ___: _).__code__.co_nlocals,
(lambda _, __, ___, ____: _).__code__.co_nlocals,
(lambda _, __: _).__code__.co_nlocals,
(lambda _: _).__code__.co_nlocals,
)
)
)```
@tribal moon :white_check_mark: Your eval job has completed with return code 0.
Hello World!
recreated but worse
@sick hound Don't use this channel to spam bot commands, use #bot-commands for that.
aok
is this were we get the skeet invites?
I've never heard of a skeet invite.
Code golf challenge of the day :
indefinitely call the function my_function
So it has to be smaller than
while 1: my_function()```
while 1:f()
bamboozeled
Clearly more fun haha
There's an interesting example in the docs
from functools import partial
with open('mydata.db', 'rb') as f:
for block in iter(partial(f.read, 64), b''):
process_block(block)```
@thin trout whats the meaning of rb option there ?
Read the file in binary mode
thanks
might be possible to get shorter with map maybe
#esoteric-python message how does this work?
it replaces the PyObject True with the PyObject NoMore. So when what is love writes True to the repl, the repr of NoMore is used
@sonic ginkgo https://github.com/decorator-factory/py-io-monad
the docs https://github.com/decorator-factory/py-io-monad/blob/master/docs/py-io-monad.pdf have some examples, but I'll add some more later
nice thank you!
it's pip installable as pip install git+https://github.com/decorator-factory/py-io-monad
btw your explanation of monads really helped me yesterday
i knew about their interpretation as a "context" but when you said "that's the only implementation that obeys the laws" something really clicked for me
well, you don't understand monads until you use them!
i was really stuck on how arbitrary it all seemed. it didnt occur to me that there might be sound theoretical reasons to define particular monads the way they are
gm also helped a lot, i never knew flatmap and bind were equivalent ideas
heh i did try to learn haskell once but didnt have the patience for it. i feel better about it now, might try again
Well, yes, there are monad laws https://wiki.haskell.org/Monad_laws
So the monad laws can be summarised in convenient Haiku form:
Monad axioms:
Kleisli composition forms
a category.
what i think i need to see is some kind of side by side equivalence of: 1) category theory monad, 2) monad-as-context, 3) monad as an abstract thing that obeys certain laws
im also grateful i took that abstract algebra class in college. it did jack shit for me in data science but its been tremendously helpful when learning programming and computer science concepts. i wouldnt be able to understand this monad laws page without it!
lst = eval(input("Enter list :"))
length = len(lst)
#List to hold unique elements
uniq = [ ]
#List to hold duplicate elements
dupl = [ ]
count = i = 0
while i < length :
element = lst[i]
#Count as 1 for the element at lst[i]
count = 1
if element not in uniq and element not in dupl:
i+=1
for j in range(i,length):
if element==lst[j]:
count+=1
#when inner llop - for loop ends
else:
print("Element",element,"frequency:",count)
if count==1:
uniq.append(element)
else:
depl.append(element)
#When element is found in uniq or dupl lists
else:
i+=1
print("Original list",lst)
print("Unique elemts list",uniq)
print("Duplicates elements list",dupl)
why I'm getting error? Help anyone!
Not very esoteric. Try the help channels.
uhh what exactly does esotoric mean? (i have a basic idea but idk if im right)
is it somewhat like brainfuck?
basically
stuff that is purposefully made to be understood only by a small group of people
you could think of it as
complexity for the sake of complexity
can i make my own esotoric language in python, then?
kind of
you could implement your own lexer and parser
like brainfuck
yeah
I interpret 'esoteric' as not currently popular.
wouldn't that be "unpopular"
That has negative connotations.
An interpreter is like any other program you'd write: it has inputs and output. It should input a program, and output whatever that program would output when run.
A brainfuck interpreter is one way to start.
!e
p="+++++++++++++++[>++>+++>++++>+++++>++++++>+++++++>++++++++<<<<<<<-]+++++++++++++++>>>>+++++.>>----.>------.------.<<<<<<++.>>------.<<<-----."
s,a='',[0]*32;j=t=0
for i in p:s+=' '*t+'j-=1 a[j]+=1 j+=1 a[j]-=1 print(end=chr(a[j])) while+a[j]: # # # #'.split()[ord(i)%18-6]+'\n';t+=(i>'Z')-2*(i>'[')
exec(s)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
Perl 6
that's one way to make a brainfuck interpreter...
delete this
Hey, maybe we can revive the idea of collaborative projects here.
<#esoteric-python message>
repl.it has added the teams feature
given that it also has integration with github, it's pretty convenient
aiohttp probably, but these kinds of questions belong in #networks or #python-discussion
[[]for*globals()[().__class__.__name__[False]],in[input(chr(62)*len([(),(),()])+chr(30))]].clear()or[print(item[False],end="")for*item,in[t][False]][False]```
I think you meant chr(32)
oh yeah my bad
[[]for*globals()[().__class__.__name__[False]],in[input(chr(62)*len([(),(),()])+chr(32))]].clear()or[print(item[False],end="")for*item,in[t][False]][False]```
it didn't show for me cause I was using the IDLE shell
smh my head
this computer is garbage it can't handle other good IDEs
@tribal moon whats the purpose of that
nothing lol it's useless
I'm thinking about the collaborative project idea. What if we made a discord bot, so everyone could contribute strange commands with incomprehensible code?
The idea is for every person to individually write one quirky command.
I can host a utility endpoint for running esoteric languages
so that the bot doesn't have to worry about timeout and CPU etc.
I def think a good thing for the bot would be a !execremote or something where it would pull the contents of a link and exec it in a snekbox
So the actual code is still safe, just no longer contstrained to discord's text limits
well, I was able to execute code which is way larger than 2000 characters by using gzip and base85 🙂
but I, of course, had to link it as a paste as well
gzip is good at compressing
@rugged sparrow feel free to open an issue for it on the bot repo
That sounds rather serious and useful for an esoteric bot.
@whole kiln would a pull request be considered do you think? I'm happy to implement it
I'm not sure.
If you open an issue, it can be discussed if we want to accept such feature
can someone help me in #help-broccoli
yo does anyone know how to make a simple esoteric lang in python?
(please mention me while replying as i have multiple tabs and servers open, thank you)
I made some languages with lark-parser
Examples being https://repl.it/@int6h/GlorifiedLambdaCalculus, https://repl.it/@int6h/FormDSL#turing_complete.rb (doesn't have any docs besides https://gist.github.com/decorator-factory/7c0fa628f715e141e5ba4d9c9ae51eb8), <https://github.com/decorator-factory/py-lark-lispy (no real docs, but you can look in bif.py and also tests/literally anything, there's also an implementation tutorial in progress https://github.com/decorator-factory/py-lark-lispy, the library author didn't hate it so it might get included officially later).
The library itself has a pretty good tutorial on parsing JSON.
@cerulean ledge
Another place to start is abusing Python syntax to make your own esolang (ask @brisk zenith )
oh hey i did that
That's why I pinged you!
@formal sandal wait so can i make my own file extensions/formats too?
so your esolang's format is .xmu, right?
your*
@modest glade really?
fixed it cat pussy
@cerulean ledge A format and an extension are orthogonal. an extension is just a way of signalling to the file system/other service what kind of data it has.
and an extension is just a part of a name
a format can exist even in your head
a format is a shape of the data, kind of. a protocol
no i meant like the system knows that a.py is a python file and opens it with python.exe and shows the python interpreter's icon
yes
so how do i make the system learn my lang's extension(s)?
(like not just my system but all systems in general)
programs with custom formats usually have an option to configure the OS on installation
like Python on windows
I was pinged here? 
and deleted too
oh I think I know who it was lmao
@sick hound
like Python on windows
@formal sandal so i have to make different versions for different OSs?
well, yes, this is OS-specific.
@cerulean ledge is that who it was?
yes
please don't move your off-topic interaction with Mr.Python into here
I don't really care about opening a file from the file manager, I usually do it explicitly and/or via the terminal
hmm
So I don't thing it's that important. If it's an esolang, it's not meant for practical purposes
@cerulean ledge while procrastinating over some discrete mathematics homework, I made another language
and I actually solved one task from discrete maths with it: https://repl.it/@esotericpython/smallfunclang#program.hs
What!?
The task was: given a public RSA key and a message, find the private key
Yo like can you also make a language called Nice or NiceLang? Just like brainfuck but + is replaced by 420 and - is replaced by 69?
(the key was, of course, very small)
And < and > replaced by (69+420)/2 - 1 and (69+420)/2 + 1?
from lib import go_brrrr
with open("program.hs") as file:
code = file.read()
go_brrrr(code)``` lol
yeah
the implementation of this and FormDSL is rather sloppy
I was kind of exploring the possibilities
@cerulean ledge You could take a look at https://esolangs.org/wiki/Brainfuck_implementations for inspiration on how something like brainfuck is made.
Hello, I was wondering if it is possible to add more than one element per time during a list comprehension like this
data = [a[1:3] for a in listOfAs] # this makes data a list of lists...
data = [*a[1:3] for a in listOfAs] # error...
I don't think it is possible but maybe someone knows an elegant workaroud, something better than
data = []
for b in [a[1:3] for a in listOfAs]:
garbabe = [data.append(c) for c in b]
or even worse:
data = []
for a in listOfAs:
for v in a[1:3]:
data.append(v)
to explain myself better: say listOfAs is [[0,1,2],[2,3,4],[4,5,6]] I am trying to extract [1,2,3,4,5,6]
sum(iterable_of_lists, [])
you can also iterate over the inner list like
data = [elem for a in listOfAs for elem in a[1:3]]
to think that i ignored a built-in function is one thing, to see it's even one named "sum" is really making me feel bad
thank you very much
wow lakmatiol that is great too
i never imagined you could concatenate comprehensions
def fib(n):
return max(
d.b
for d in [fib]
for d.a, d.b in [(0, 1)]
for _ in range(n)
for d.a, d.b in [[d.b, d.a + d.b]]
)
```can even do this
we need to release business cards with this
I have successfully defeated the coding interview, ><
although, it starts at 0, not 1
!e ```py
conditions = {
lambda x: sum((x % 5, x % 3)) == 0: "FizzBuzz",
lambda x: x % 5 == 0: "Buzz",
lambda x: x % 3 == 0: "Fizz",
}
for i in range(1, 101):
for check, output in conditions.items():
if check(i):
print(output)
@distant wave :white_check_mark: Your eval job has completed with return code 0.
001 | Fizz
002 | Buzz
003 | Fizz
004 | Fizz
005 | Buzz
006 | Fizz
007 | FizzBuzz
008 | Buzz
009 | Fizz
010 | Fizz
011 | Buzz
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/upotukobit
hey, there's code duplication!
We need a compendium of the best of these cool things, like the comprehension Fibonacci.
I made a team on repl.it, maybe people could register on that service so I can add them. https://repl.it/repls/@esotericpython
It also has github integration.
I can't see how to join, so I assume I need to send you my own username.
there seems to be a bug with repl.it, maybe someone else can tell their username so that I can add them
It'll likely be over in a day or two after the initial rush for the repl.it language design jam is over.
about that fibonacci @proper vault i know we are in the esoteric channel but i think that this kind of abstraction of python is to be used to create more expressive and short and maintainable code, meaning it should also be easily understood.. still I understand the artistic value of it 😆
that is to say i'm having a tough time understanding how it works
would you expand on it?
for x in [value] is essentially x = value
just like regular assignments and unlike :=, comprehensions can unpack
another point is that functions are proper __dict__ backed objects, so they have mutable attributes
In [43]: x = lambda: None
In [44]: vars(x)
Out[44]: {}
In [45]: x.y = 5
In [46]: vars(x)
Out[46]: {'y': 5}
and that is pretty much it
singleton for is like let ... in expressions in some functional languages
some version IIRC should optimize them to simple assignments, but I may be misremembering
Fun fact, there’s actually a magic algorithm to directly calculate any Fibonacci number
You mean using the exact formula, as a difference of two geometrical progressions?
I tried to make it work once, but I discovered that the precision required (using decimals) grew so fast with n, and calculation speed dropped so fast with precision, that it was actually much faster to use the iterative algorithm.
The best way I know of is the O(logn) algo. You actually compute fibs faster than you can convert them to string
The one that uses the golden ratio
one/ones
I just thought it was cool that it's possible to directly calculate a Fib number without knowing/using any other number in the sequence
yeah, that's the one I'm talking about
it was fun when I was showed how to derive that formula in my linear algebra course
tell me if you actually make it work faster than
def fib(n):
if not isinstance(n,int):
raise TypeError
if n<0:
raise ValueError
if n<=1:
return 1
a,b = 1,2
for _ in range(n-2):
a,b=b,a+b
return b
😛
you can use this doubling method
I think I can make it much faster
def fibonacci(n):
return np.floor(1 / np.sqrt(5) * (((1 + np.sqrt(5)) / 2) ** n - ((1 - np.sqrt(5)) / 2) ** n))
runs 6x faster than your implementation by me
that's the way I was talking about, except that it doesn't work right
In [119]: for i in range(100):
...: if abs(fib(i)-fibonacci(i+1)) > 0.001:
...: print(i)
...: break
...:
71
doesn't work right, what do you mean?
In [121]: fib(71),fibonacci(72)
Out[121]: (498454011879264, 498454011879265.0)
off by one at 71 already.
it'll be worse later.
(I tried this method too 🙂 )
Also, at around 1400 it overflows.
decimals with high precision make it work right, but the speed loss is so fast that it ends up slower than the basic algorithm.
I tried to make it work once, but I discovered that the precision required (using
decimals) grew so fast withn, and calculation speed dropped so fast with precision, that it was actually much faster to use the iterative algorithm.
let me try something...
Depending on the implementation (and how much of fib you need) a lot of production code just hard codes it
the idea was to use the binomial expansion of (1 + np.sqrt(5))**n, same for (1 - np.sqrt(5))**n, every second term simplifies (adding and subtracting the same quantity) you keep the remaining terms in an array and you sum over this array
thus avoiding the overflow due to computing (1 + np.sqrt(5))**n directly
You might be able to represent sqrt(5) as a repeating continued fraction.
Oh, that's right, φ is just [1; 1, 1, 1, ... ] as a continued fraction.
something like that:
def fibonacci(n):
coeffs = np.array(binom(2 * k, n) for k in range(int(n/2)))])
terms = np.array([np.power(np.sqrt(5), 2*k) for k in range(int(n/2))])
res = np.multiply(coeffs, terms)
res = np.power(res, 2*n-1)
res = np.multiply(np.divide(1, np.sqrt(5)))
return res
from scipy.special import binom before
rather this:
import numpy as np
from scipy.special import binom
def fibonacci(n):
coeffs = np.array([binom(n, 2 * k + 1) for k in range(int(n/2))])
terms = np.array([np.power(np.sqrt(5), 2*k+1) for k in range(int(n/2))])
res = np.multiply(coeffs, terms)
res = np.sum(res)
res = np.divide(res, 2**n)
res = np.multiply(np.divide(1, np.sqrt(5)), res)
return np.floor(res)
```python
anyway, it also overflows
Does anyone know an algorithm for raising a number in continued fraction format to some power? Other than repeated multiplication, that is.
Fibonacci is harder to crack as I thought 😉
not crucial, but vectorising the construction of coeffs and terms might speed it up
the crucial thing is the trouble with computing the powers...
there is a small bug somewhere in the code above (it's 1:36 am by me...) but even if fixed it can anyway not compute terms...
for n too big, that is
This might be of use: https://pdfs.semanticscholar.org/4df1/c943c01e7407ae2294512209802ba78b92f2.pdf
Apparently there's a 'product of factors' algorithm which is fast.
fixed version:
import numpy as np
from scipy.special import binom
def fibonacci(n):
n += 1
coeffs = np.array([binom(n, 2 * k + 1) for k in range(int(n/2))])
terms = np.array([np.power(np.sqrt(5), 2*k+1) for k in range(int(n/2))])
res = np.multiply(coeffs, terms)
res = np.sum(res)
res = np.divide(res, 2**(n-1))
res = np.multiply(np.divide(1, np.sqrt(5)), res)
return np.floor(res)
the crucial thing is the trouble with computing the powers...
@sharp jacinth yes, that's why I said it wasn't crucial (and not directly relevant to the problem)
sqrt(5) can also be 5**.5
compute it separately
this goes better:
def fibonacci(n):
n += 1
coeffs = np.array([np.log(binom(n, 2 * k + 1)) for k in range(int(n/2))])
terms = np.array([np.multiply(np.log(np.sqrt(5)), 2*k+1) for k in range(int(n/2))])
res = np.exp(np.add(coeffs, terms))
res = np.sum(res)
res = np.log(res)
res = np.subtract(res, np.log(2)*(n-1))
res = np.exp(res)
res = np.multiply(np.divide(1, np.sqrt(5)), res)
return np.floor(res)
this time it doesn't overflow by terms but the line after
something like:
ks = np.arange(n // 2)
coefs = binom(n, np.arange(2 * ks + 1))
going to log in order to avoid overflow due to power
why don't you just use operators/methods instead of calls to numpy top-level functions
there is only this np.exp() left to crack...
it seems that it will overflow "eventually" anyway...
can't really get around fixed-width types
def fibonacci(n):
n += 1
coeffs = np.array([np.log(binom(n, 2 * k + 1)) for k in range(int(n/2))])
terms = np.array([np.multiply(np.log(np.sqrt(5)), 2*k+1) for k in range(int(n/2))])
res = np.add(coeffs, terms)
res = np.subtract(res, np.log(2)*(n-1) + np.log(np.sqrt(5)))
res = np.exp(res)
res = np.sum(res)
return np.floor(res)
overflow solved for exp, now it's by sum...
with this implementation it manages to go until n=1000 at least
with the previous implementation it went only until n=600
optimized version:
def fibonacci(n):
n += 1
ks = np.arange(n // 2)
coeffs = np.log(binom(n, 2 * ks + 1))
terms = np.multiply(np.log(np.sqrt(5)), 2*ks+1)
res = np.add(coeffs, terms)
res = np.subtract(res, np.log(2)*(n-1) + np.log(np.sqrt(5)))
res = np.exp(res)
res = np.sum(res)
return res
is 30% slower than fib() for n=1000
but as n increases, the time gap between both reduces... if it wouldn't overflow at n=1000 it would be more efficient for large ns
for n=10 fib() is 20x faster, for n=1000 it's only 1.3x faster
I would guess that the logarithms are killing it
yes it's the computation of coeffs
but I have an idea to push the overflow limit...
import numpy as np
def log_binom(n, ks):
r = np.arange(n) + 1
r = np.log(r)
s = np.sum(r)
r1 = np.cumsum(r[ks])
r2 = r1[::-1]
r = np.add(r1, r2)
return np.subtract(s, r)
def fibonacci(n):
n += 1
ks = np.arange(n // 2)
# coeffs = np.log(binom(n, 2 * ks + 1))
coeffs = log_binom(n, 2 * ks + 1)
terms = np.multiply(np.log(np.sqrt(5)), 2*ks+1)
res = np.add(coeffs, terms)
res = np.subtract(res, np.log(2)*(n-1) + np.log(np.sqrt(5)))
# print(np.max(res))
res = np.exp(res)
res = np.sum(res)
return res
it overflows by exp() but if you are content with having the result splitted in n elements to sum, it's 3x faster than fib() for n=10000
log_binom() is just computing the binomial coefficient the normal way but taking the log before and not after the factorial
@sharp jacinth might I hazard a guess @ your background
pure mathematics?
not computer science, right
both
where are you from?
you mean, geographically?
yes
southeast Asia
import numpy as np
def log_binom(n, ks):
r = np.arange(n) + 1
r = np.log(r)
s = np.sum(r)
r1 = np.cumsum(r[ks])
r2 = r1[::-1]
r = np.add(r1, r2)
return np.subtract(s, r)
def fibonacci(n):
n += 1
ks = np.arange(n // 2)
# coeffs = np.log(binom(n, 2 * ks + 1))
coeffs = log_binom(n, 2 * ks + 1)
terms = np.multiply(np.log(np.sqrt(5)), 2*ks+1)
res = np.add(coeffs, terms)
res = np.subtract(res, np.log(2)*(n-1) + np.log(np.sqrt(5)))
m = np.max(res)
res = np.divide(res, m)
res = np.exp(res)
res = np.sum(res)
return res, m
the result is res x exp(m)
so you avoid reaching the max type width
and it gets much faster than fib() for large n
southeast Asia, south Korea?
well I am from France... after high school there is a study called "classes préparatoires", "preparation classes" where you study mqth and physics super intensively, and then you go to enginnering school, in my case I studies CS and statistics there
I see
your coding style is kind of...
I would say it seems to me like someone who studied mathematics first
but perhaps that is just my personal bias
good guess, I studied math forst 😉
well, I am also kind of fanatic when a take a challenge
yeah, I understand what you mean
and for what it's worth this is an interesting problem, I think
actually, at this point, would you consider moving away from numpy and using normal Python?
would defeat the purpose of getting a faster solution than your initial implementation
this implementation was already very good
as you saw, beating it required quite a lot of effort
for me at least, maybe a genius would have come up with my solution in 3 minutes instead of 3 hours 😉
who made it?
the other aspect about runtime is that your implementation is not parallelizable, whereas mine is (besides the cumsum operation)
but theoretically both run in O(n)
(well, cumsum() is parallelizable through map-reduce)
gm, what would be the advantage of moving away from numpy?
depends what you are trying to do - e.g. the internal statistics module is now relatively useful.
I found this challenge very interesting, so much that I wrote an article on Medium about it: https://medium.com/@manuel.capel_60823/fastest-fibonacci-9273e2a1805d
Apparently this algorithm is even faster than the fast doubling algorithm for large n, considered so far as the fastest algo to compute Fibonacci numbers
@sharp jacinth what is n in the fibbonaci function, it doesn't seem to match up with the nth fibbonaci number
!e
import numpy as np
from math import exp
def log_binom(n, ks):
r = np.arange(n) + 1
r = np.log(r)
s = np.sum(r)
r1 = np.cumsum(r[ks])
r2 = r1[::-1]
r = np.add(r1, r2)
return np.subtract(s, r)
def fibonacci(n):
n += 1
ks = np.arange(n // 2)
# coeffs = np.log(binom(n, 2 * ks + 1))
coeffs = log_binom(n, 2 * ks + 1)
terms = np.multiply(np.log(np.sqrt(5)), 2*ks+1)
res = np.add(coeffs, terms)
res = np.subtract(res, np.log(2)*(n-1) + np.log(np.sqrt(5)))
m = np.max(res)
res = np.divide(res, m)
res = np.exp(res)
res = np.sum(res)
return res, m
for k in range(10, 15):
res, m = fibonacci(k)
print(res * exp(m))
@proper vault :white_check_mark: Your eval job has completed with return code 0.
001 | 32440.833911573744
002 | 95699.17798820164
003 | 651189.9445876549
004 | 1874011.7677795521
005 | 14554702.66861242
hmm let me check
good news: the function fibonacci() is correct, bad new: the function log_binom() is wrong sorry
I fixed the error, the functions in the article are correct now... performance is the same
thanks for having pointed this out
import numpy as np
def log_binom(n, ks):
r = np.arange(n) + 1
r = np.log(r)
s = np.sum(r)
r = np.cumsum(r)
z = np.zeros(r.shape[0] + 1)
z[1:] = r
z1 = z[::-1]
z = np.add(z, z1)
z = np.subtract(s, z)
return z[ks]
def fibonacci(n):
n += 1
ks = np.arange(np.ceil(n / 2)).astype(np.uint32)
coeffs = log_binom(n, 2 * ks + 1).astype(np.float64)
terms = np.multiply(np.log(np.sqrt(5)), 2*ks+1)
res = np.add(coeffs, terms)
res = np.subtract(res, np.log(2)*(n-1) + np.log(np.sqrt(5)))
m = np.max(res)
res = np.subtract(res, m)
res = np.exp(res)
res = np.sum(res)
return res, m
How would you break this down task = filter(lambda t: t['id'] == id, tasks)?
That filter would return a generator of all elements of tasks that match that condition.
To get the first (and only, unless tasks have duplicate ids) element of that generator, next() is also needed.
that's very similar to:
def f(tasks, id):
for t in tasks:
if t['id'] == id:
yield t
thanks
@sharp jacinth
well I am from France... after high school there is a study called "classes préparatoires", "preparation classes" where you study mqth and physics super intensively, and then you go to enginnering school, in my case I studies CS and statistics there
I suspected you had a cs major the moment I saw the medium link. Lol
why did you suspect this?
!e
numbers = range(42)
print(numbers, type(numbers))
print(numbers[5:2])
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | range(0, 42) <class 'range'>
002 | range(5, 2)
@polar plover This is technically correct, but it's really weird.
yhe
!e
numbers = range(42)
print(numbers, type(numbers))
shmumbers = numbers[5:2]
print(shmumbers)
print(shmumbers[::-1])
print(shmumbers[::-1][::-1])
👀
they work like lists
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | range(0, 42) <class 'range'>
002 | range(5, 2)
003 | range(4, 4, -1)
004 | range(5, 5)
!e py print(range(0, 10, 2)[3])
@polar plover :white_check_mark: Your eval job has completed with return code 0.
6
Yes, I've seen the slicing thing
!e py shmumbers = range(5, 2) print(shmumbers) print(shmumbers[:])
@stark fable :white_check_mark: Your eval job has completed with return code 0.
001 | range(5, 2)
002 | range(5, 5)
I was puzzled about the range(5,2) thing
what
Well, technically, it's correct. They contain the same elements.
object and object[:] should be the same thing wth
They are
they're both empty ```py
list(range(5, 2))
[]
list(range(5, 2)[:])
[]```
range(5, 2) <=> range(5, 5) <=> range(666, 666) <=> range(100000000000, 0)
just different notation
it just feels wrong xD
yes
!e py print(range(0, 10, 2)[::2])
@polar plover :white_check_mark: Your eval job has completed with return code 0.
range(0, 10, 4)
!e ```py
def mult(a: int, b: int) -> int:
return range(0, 10)[::a][::b].step
print(mult(6, 10))```
@polar plover :white_check_mark: Your eval job has completed with return code 0.
60
🙃
you can define addition as py def add(a: int, b: int) -> int: return range(range(0)[::range(a,2)[:].stop][::range(b,2)[:].stop].step)[a:][b:].start
or a bit more readably as ```py
def mult(a: int, b: int) -> int:
return range(0)[::a][::b].step
def max(a: int, b: int) -> int:
return range(a,b)[:].stop
def add(a: int, b: int) -> int:
return range(mult(max(a,2),max(b,2)))[a:][b:].start```
is there a Python obfuscated code contest going on there? 😉
though it's still interesting to see
its not really a contest, more of a look at all these cool ways to write bad python code
correction: intentionally writing bad python code 🙂
I guess so
ye
Good news, I was able to set up a website on repl.it that runs on my esolang. Maybe we could implement some kind of message board for esoteric python stuff.
Turns out that you can open bash via the interactive console and even run emacs or vim.
I think this brings about many esoteric projects:
- database
- web framework
- interoperability with Haskell
...
how can I further reduce character count of this lambda?
o=lambda r:r==1&1 or o(r-1)+2*(r-1)
I'm using bitwise & to return 1 if r==1
how does one replace logical or with bitwise operators
Logical or does short-circuiting so as to not execute the right half unless it needs to, so you can't replace it with bitwise |.
I think this is the shortest we've gotten Fibonacci: https://ptb.discordapp.com/channels/267624335836053506/470884583684964352/540655731909853235
I expect it's as simple as adding a *2 to it.
2*(r-1) (7 chars) is the same as 2*r-2 (5 chars)
@frank jacinth
(assuming r is a sensible value and not a confusing user-defined type)
You can slap the or to the 1 like this 1or, and it will still correctly parse
You can slap the
orto the 1 like this1or, and it will still correctly parse
@thin trout now THIS I did not know
the gift of surprises is the greatest gift of all
!e
2or[1,2]and(1,2,3)
@formal sandal :warning: Your eval job has completed with return code 0.
[No output]
@high garnet However, you can't do 0or because it will try to interpret it as an octal literal, it seems
!e
0or[1,2]and(1,2,3)
@formal sandal :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | SyntaxError: invalid octal literal
Cool, thanks
I just assumed keywords had to have spaces separating them
!e
o=lambda r:r==1oro(r-1)+2*(r-1)
o(5)
@frank jacinth :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | o=lambda r:r==1oro(r-1)+2*(r-1)
003 | ^
004 | SyntaxError: invalid syntax
It seems there needs to be a space before the function name
!e
o=lambda r:r==1or o(r-1)+2*(r-1)
@frank jacinth :warning: Your eval job has completed with return code 0.
[No output]
it's more that there needs to be a space after or
@frank jacinth :warning: Your eval job has completed with return code 0.
[No output]
ok well it's because you can't have an identifier after or without a space in between
the parser interprets oro as oro, not or o
so im learning python and trying to follow pep, how is this
class BoopBoop():
def BorpBif(BepaBip, BupBup):
BapBif = BepaBip
Bip = ""
BopBip = Bip.join(BapBif)
BepBid = "urgle"
BufBip = (BopBip+" "+BupBup+BepBid)
print(BufBip)
def Bobbup(Blup):
BupBup = Blup
BefBip = {
"BabBab":"a", "BadBab":"b", "BabBap":"c", "BabBad":"d",
"BebBeb":"e", "BedBeb":"f", "BedBep":"g", "BebBed":"h",
"BibBib":"i", "BidBib":"j", "BidBip":"k", "BibBid":"l",
"BobBob":"m", "BodBob":"n", "BodBop":"o", "BobBod":"p",
"BubBub":"q", "BudBub":"r", "BudBup":"s", "BubBud":"t",
"BaabBaab":"u", "BaadBaab":"v", "BaadBaap":"w", "BaabBaad":"x",
"BoobBoob":"y", "BoodBoob":"z", "BoobBoop":" "
}
BepaBip = (BefBip["BoobBoob"],BefBip["BodBop"],BefBip["BaabBaab"],BefBip["BudBub"],BefBip["BoobBoop"],
BefBip["BodBob"],BefBip["BabBab"],BefBip["BobBob"],BefBip["BebBeb"],BefBip["BoobBoop"],BefBip["BibBib"],BefBip["BudBup"])
BoopBoop.BorpBif(BepaBip, BupBup)
def BipBop(BaapBip, Bup):
BupBeep = (BaapBip*Bup)
BepBep = (''.join(sorted(BupBeep)))
Blup = (BepBep[len("ba")]+BepBep[len("Boof")])
BoopBoop.Bobbup(Blup)
def BopBid():
Bup = len("Bap")
BoopBip = "BabBoop>>>"
BaapBip = input(BoopBip)
BoopBoop.BipBop(BaapBip, Bup)
if __name__ == '__main__':
BoopBoop.BopBid()```
boop bop beep
if you run it and type in your name it gives you a new nick name
by pep 8, function names should be lower_case_seperated_by_underscores
ah damn, i thought i was missing something
as should variable names
Is that exactly the same as the one you posted in 2019?
Not esoteric just, horribly unreadable 😄
legit disassembler code is more readable
Wanna bet
have you ever tried disassembling your libraries? 😉
Is there a de-facto shortest fizzbuzz method without if statementss? I actually got asked to do fizzbuzz in an interview this week
I managed to get this return'Fizz'*(n%3==0)+'Buzz'*(n%5==0)or str(n) but couldnt think of a way to get rid of the or
What kind of people ask you to show your esoteric skills haha
Smart
I have no fucking idea what happens there
lmao
@covert mulch python "Fizz"*(n%3==0)+"Buzz"*(n%5==0)+f"{n}" for your version
function calls are very expensive in python
The bitmask-modulo is a known trick, but I forgot what it exactly does
same
it's to prevent having a negative number in addition to its usual use (preventing too big a one), I guess; otherwise, it poses a problem with small n. I.e. with n=1 : n-3&4 makes 4, whereas n-3 would be -2, witch would cause problems when used for indexing
Here's a weird thing that's faster than the normal solution.
Suppose you want to do an operation over an iterator that doesn't return anything you need, like printing them.
Normal solution:
def for_sol(n):
lst = []
for i in range(n):
lst.append(i)
(here, I'm appending elements to some list)
"Bad"(PEP8-violating) listcomp solution:
def listcomp_sol(n):
lst = []
[lst.append(i) for i in range(n)]
Weird map solution:
def deplete(iterator): # to force a generator to calculate the elements
for el in iterator:
pass
def map_sol(n):
lst = []
deplete(map(lst.append,range(n)))
Results:
In [50]: %timeit for_sol(100)
7.09 чs + 289 ns per loop (mean + std. dev. of 7 runs, 100000 loops each)
In [51]: %timeit map_sol(100)
4.62 чs + 266 ns per loop (mean + std. dev. of 7 runs, 100000 loops each)
In [52]: %timeit listcomp_sol(100)
8.92 чs + 235 ns per loop (mean + std. dev. of 7 runs, 100000 loops each)
The listcomp solution is indeed bad, but using map with a function the return of which we don't care about is faster than a for-loop.
that is probably only true of the map function is a builtin. For user functions, I do not think it would work
that's true. list.append is written in C, while user functions written in python have a lot of calling overhead which is what makes them quite slow (relatively speaking)
I can explain it in several ways :
mapmakes the loop in C, witch is much faster (it's the reason we have numpy 😄)- You're avoiding looking up
lst.appendevery time; the dot operator doesn't look it, but it's quite expensive (or so I heard). You could haveappend = lst.appendin your other functions as well, and then just useappend(elt)in the loop, it should go faster.
fun challenge someone posted in #python-discussion as a question:
write a function f(n) that returns the digit at index n from the string
11212312341234561234567...
the string is just a concatenation of 1, 12, 123, 1234, 12345 ...
the idea was to optimize this for speed
That's a decent-diff codewars kata.
Hmm, maybe not quite, I think that was 1234567891011...
i found it pretty interesting to solve
haha @hard spoke i didnt read the question in the link and assumed it was the same as mine, not the one you posted. was very confused why mine didnt work
is a O(1) possible here?
but for mine this is my solution:
g = lambda n: n - f(int(f_(n))) + 1
f = lambda x: 0.5 * np.power(x, 2.) - 0.5 * x + 1.
f_ = lambda x: 0.5 + 0.5 * np.sqrt(8*x-7)
not using math i came up with this solution:
def g(n):
x = 1
index = 0
while True:
index += 1
x += index
if x > n:
x -= index
break
return n - x + 1
haha @hard spoke i didnt read the question in the link and assumed it was the same as mine, not the one you posted. was very confused why mine didnt work
@grizzled cloak
It is, though, isn't it?
