#internals-and-peps
1 messages · Page 91 of 1
You are not allowed to use that command here. Please use the #bot-commands channel instead.
!e
x = 0
y = 0
def f():
x = 1
y = 1
class C:
nonlocal x
print(x, y) # What does this print?
x = 2
f()
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
1 1
That will print 1 1 without the local assignment in the class scope
so why does it not care about y
Right tnx
It's the local assignment that changes the behavior
That in itself is not odd, for a function that triggers the UnboundLocalError
I'm just a bit surprised that it does something different for classes
!e
def f():
y = 1
def g():
print(y) # NO Error!
g()
f()
@stable grail :white_check_mark: Your eval job has completed with return code 0.
1
Yep, it is resolving it through the closure since you did not reassign y
@stable grail Indeed, it's the local assignment that makes the difference
Both in the case of the function (error) or the class (suddenly a global lookup, bypassing the nonlocal scope/closure)
but why would something on line number n+1 change the line n
thats what i find the most interesting
The same as it does for functions: Python will recognise it as a name that's local to that scope
def f():
y = 1
def g():
print(y)
y = 2 # error because of a n+1 line
g()
f()
meaning it creates the scope first
My best guess is that variables are resolved at compile time, that’s a pretty standard procedure
What do you mean by that?
It will very much use the value that you determine at runtime
say that you do this:
def f():
x = 1
y = 1
class C:
print(x, y) # What does this print?
x = 2
x = 10
f()
x = 12
f()
x = input("> ")
f()
it would do exactly as you expect
10, 12, whatever you input
I think what is happening here is that at some point during the compilation procedure, the compiler will walk the whole tree and assign numerical value to each variable (the bytecode arguments). When doing this pass, if it sees an assignment, it will consider that variable as being global, and change the instruction used to look it up.
Right, but why is it different for classes compared to functions?
What you're saying is basically just restating what happens, right?
Yeah, that’ my guess of why this happening
Although I’m not sure why it is thowing an exception in one case
Well, for functions, the behavior is apparently different than for classes
allegedly different. im not so sure it is that different
The difference is that a function throws an exception if you try this, while a class looks at the global scope for the value before it's assigned locally
classes dont need nonlocal to keep track of the reference to a name.
it just picks one from the outermost scope
while a nested function cant
using nonlocal in a nested structure is kinda the solution to get a correct answer
but, without the local assignment, the class does look at the enclosing scope
that's why y=1 for the class
like, why would a class look in the enclosing scope?
Something to note is that we assign a class attribute on the class, while we create a local with the function
Not sure, but it does do that
x = 0
y = 0
def f():
x = 1
y = 1
class C:
print(x, y) # y=1 from the enclosing function scope, x=0 from the global scope
x = 2
f()
What instruction do they use for assigment?
whats the qualname of C ?
!e
x = 0
y = 0
def f():
x = 1
y = 1
class C:
print(x, y) # What does this print?
x = 2
print(C.__qualname__)
f()
@stable grail :white_check_mark: Your eval job has completed with return code 0.
001 | 0 1
002 | f.<locals>.C
Make sense
!e
x = 0
y = 0
def f():
x = 1
y = 1
class C:
print(x.__qualname__, y.__qualname__) # What does this print?
x = 2
f()```
@undone hare :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 11, in <module>
003 | File "<string>", line 8, in f
004 | File "<string>", line 9, in C
005 | AttributeError: 'int' object has no attribute '__qualname__'
Hmm.. is there a way around that?
My guess is that the behavior is the same for Python 2
I think the special sauce here is that the generated bytecodes are different if the current block is a function
The original post is in Py 2
Probably to better support closures
They use the print statement
if you swap class an function around, having class as the first level, will it still be the same?
You'd get an UnboundLocalError I assume
It will be 0 0 since the second definition will create class attributes
as then you're referencing a local name before the assignment in a function scope
Or maybe just error out
what if you create nested functions with name binding
!e
x = 0
y = 0
class C:
x = 1
y = 1
def f():
print(x, y)
x = 2
f()
@wide shuttle :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 "<string>", line 12, in C
004 | File "<string>", line 9, in f
005 | UnboundLocalError: local variable 'x' referenced before assignment
Alright, so that’s pretty consistent
I have a guess
If we remove the assignment, you should get the global scope
!e
x = 0
y = 0
class C:
x = 1
y = 1
def f():
print(x, y) # 0 0 ?
f()
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
0 0
right, makes sense
just like with other things that create a local scope within a class scope (e.g., the list comprehension above)
With the class? Of course since you create class attributes
that doesn't really matter, you can use the names
just not from within another local scope that you're creating
!e
x = 0
y = 0
class C:
x = 1
y = 1
def f(x, y):
print(x, y) # 1 1
f(x, y)
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
1 1
so when you add everything to a class
the "highest" scope it goes to is the <local> scope
so if we make something that has a very nested qualname
f.<local>.c.<local>.G
what local scope would it get the value from
im thinking that it gets it from the closest local scope
and the rest from the global
Hmm that’s interesting
you might not be able to create this though
my first attempt failed
can you only have one local scope?
I don't think your logic is quite right
!e
x = 0
y = 0
def a():
x = 1
y = 1 # <- will happily use the second enclosing scope for y
def b():
x = 2
class Foo:
print(x, y)
x = 3
b()
a()
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
0 1
unless I misunderstood your argument
!e
def f():
def g():
def h():
pass
return h
return g
print(f().__qualname__)
@stable grail :white_check_mark: Your eval job has completed with return code 0.
f.<locals>.g
im just wondering why h is left out
you never called g
!e
def f():
def g():
def h():
pass
return h
print(g().__qualname__)
return g
print(f().__qualname__)
@stable grail :white_check_mark: Your eval job has completed with return code 0.
001 | f.<locals>.g.<locals>.h
002 | f.<locals>.g
You never called g in the first snippet
So, you never actually create h or return it from somewhere
yeah, you where my rubber duck @wide shuttle 😄

!e
x = 0
y = 0
def f():
x = 1
y = 1
def g():
x = 2
y = 2
class H():
print(x, y)
x = 3
return g()
f()
@stable grail :white_check_mark: Your eval job has completed with return code 0.
0 2
notice it only goes one local scope up
f.<locals>.g.<locals>.h
it picks the values from the first local scope
ist that a bit interesting as well @wide shuttle @undone hare ?
how does that even work?
is the local scope moved on top of a stack or?
since the values are not destroyed
!e
x = 0
y = 0
def f():
x = 1
y = 1
def g():
x = 2
y = 2
class H():
print(x, y)
x = 3
print(x, y)
return g()
f()
@stable grail :white_check_mark: Your eval job has completed with return code 0.
001 | 1 1
002 | 0 2
Those names will probably be turned into distinct numbered names
I think that's what happens for local names and closures
and maybe thats what it does, just "pick the next local scope from the stack"
And then the look-up order goes down the enclosing scopes again
i dont know much about how the stack works under the hood though
This is probably something that already happens in the compiler (to know which value to look up when)
well, if it picks from the closest local scope, then if you nest classes inside classes, it should still pick from the closest local scope right?
nah.. im just thinking.. it should not, the class attribute will catch it
this is where it gets interesting: I think this is when functions and classes start to divert in the OPCODES they produce
but the most nested class should
!e
x = 0
y = 0
def f():
x = 1
y = 1
class G:
x = 2
y = 2
class H():
print(x, y)
x = 3
return G
f()
@stable grail :white_check_mark: Your eval job has completed with return code 0.
0 1
yeah..
Consider a simple assignment statement in Python: a = b The meaning of this statement may seem trivial. What we do here is take the value of the...
Explains that the opcodes produced for functions are different
Scroll down to the last section before the conclusion
I'll have to read that
ModuleNotFoundError: No module named 'python_nbt'
what do LOL?
Hey @sonic idol This channel is not for help, please take a look at #❓|how-to-get-help
Here was an answer I found in for the #internals-and-peps message
Nope doesn’t copy X from the global scope — you can verify this by adding a ‘print locals()’ after the existing print line, or by surrounding the ‘X = 2′ with an ‘if 0:’, and checking C.dict after the class is created.
As far as I can tell this isn’t a bug, since both CPython and PyPy produce this result, though I have no idea who would rely on this behavior.
Here’s the best reference that I could find:
http://www.gossamer-threads.com/lists/python/dev/254461It’s an old thread from 2002 that seems to allude to this behavior being around for backwards compatibility. My reading is that at some point all lookups worked this way, ie this code would have printed “0 0″. Then at some point they added nested functions and changed the way that function scoping works, but didn’t apply the same change to class scoping.
The technical details are that there are a number of different opcodes that Python can use to look up names; in a function scope locals are looked up with LOAD_FAST, but in a classdef they are looked up with LOAD_NAME, which does not check any parent scopes and just skips to the global scope. Non-locals in classdefs are looked up with either LOAD_NAME or LOAD_DEREF, the latter of which will check enclosing scopes.
Not something you run into every day but something you have to get right as an implementor!
Yeah, that's a comment to the blogpost Guido links
We were wondering why it worked that way, although the answer seems to be "this is just how it works" combined with "it works differently for functions" (probably to make closures powerful for functions)
Why is NoneType not declared in builtins?
!e
import builtins
print(type(None).__module__)
print(hasattr(builtins, 'NoneType'))
You are not allowed to use that command here. Please use the #bot-commands channel instead.
001 | builtins
002 | False
Because there's almost no practical use for it, the type is not directly exposed anywhere in the stdlib afaik
ye its not
Is there even a way to get an handle to NoneType? Maybe type(None)
Yes, that's how most of the types from the types module are exposed
But you don't have access to NoneType, so how would you compare it?
No, NoneType is not in types, but most other things like FunctionType etc. are
Any it gets them just through type
def _f(): pass
FunctionType = type(_f)
Fair
Now I want to find a way to subclass NoneType
I'm sure you can break half of the interpreter by passing a type like that around
NoneType not being in builtins is a bit inconsistent though
I can't get it from types
Why?
Because type(None).__module__ says it should be in builtins?
>>> class A(type(None)):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'NoneType' is not an acceptable base type
F
So basically it's just a hack, F
There probably is a way tbh
If you use some ctypes magic to inject it in the MRO or something like that
NoneType can be a singleton as far as I know
Yeah it is
But it is singleton in the sense that it has to use some magic so that the implementation is invisible
Looks like it'll be added back in to the types module in 3.10, along with EllipsisType and NotImplementedType
Someone should publish a null package on pip 😂
The slogan should be:
null is not None
It has no real module as it's only used directly in the C implementation to set the type and create an instance so I'd guess it just uses builtins as some sort of default
Probably yeah
class Singleton(type):
"""
This class is to be used as a metaclass.
class SingletonObject(metaclass=Singleton):
...
"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class NullType(metaclass=Singleton):
def __repr__(self):
return 'null'
def __str__(self):
return 'null'
null = NullType()
doesn't work, since you can subclass NullType
It works fine though
>>> class MyNullType(NullType):
... pass
...
>>> MyNullType()
null
The builtin scope is pretty bloated already, and I wish it had less things (e.g. id and memoryview certainly don't belong there). So types is the approptiate place
Well, when it's moved to types in 3.10, type(None).__module__ should print types
Why not id?
How often is id really used? What's a reasonable use case for it?
Being able to determine the identity of an object sounds like a fundamental operation to me. I'd wager it's an important operation in Python's implementation as well.
For me, that makes it a strong candidate for being part of the builtins
x, y = 0, 0
def foo():
x, y = 1, 1
class C:
print(x, y) # 0, 1
x = 2
foo()
Has this been discussed
Being able to determine the identity of an object sounds like a fundamental operation to me.
I'm not sure what you mean by that. Can you give an example of where it would be useful in user code?
I'm not saying it should be removed, I'm just saying it shouldn't be in the built-in scope (especially considering that it's a very commonly used name on its own)
It's used within Python itself quite a few times, like equality checks for instances of user-defined classes
Obviously, you could say that such usage doesn't require it to be a builtin for users, but that makes it a fundamental operation to me
It's not some add-in provided by the standard library in addition to Python's core; it's a core feature
@wide shuttle But putting something in a different module is just a way of structuring things. Threading and multiprocessing are not "add-ins" either, nor is the dis module, or the traceback module, or the sys module.
Why is sys.getsizeof in sys, but id in the builtins?
I don't really think they are the same
dis is an additional module for disassembly, traceback provides additional traceback-related features (but you'll find all the actual exceptions raised at run time in the builtins namespace).
but maybe that's all just categorization
i would say theres an argument to be made for id to move into sys
What would be your argument?
id gets lowlevel information on an object, similar to sys.getrefcount and sys.getsizeof
I also think the name id being reserved is a bit sad.
in that case youre issue is that the list your making is moved into the internal free lists array and reused
id is guaranteed to produce a unique id as long as its argument is a live object
I'm not really sure where they'd go but I'd rather see things like compile, exec memoryview etc. to be moved first; I use id regularly when debugging something so the same argument for it staying in buitlins could be made as for breakpoint
Maybe utils but that would mess with projects that use that name internally
IIRC if you dig enough, you will find some discussions regarding moving id() into sys on py3 migration
here it is
Seems like a some mixed feelings, but quite a few people in favour of it in some form
Looks like it was initially put on the schedule for P3000 (courtesy of that first link you provided), but it was later removed from the changelist
I can't find much about that latter decision; I think it was a decision made by Guido at some point
probably
here are all the stdlib modules that use id at least once:
_threading_local, asyncio.queues, asyncio.sslproto, asyncore, codecs, concurrent.futures, cProfile, ctypes, dataclasses, distutils, doctest, gzip, idlelib, importlib, inspect, lib2to3, multiprocessing, optparse, pickle, plistlib, pprint, pydoc_data, reprlib, tarfile, threading, tkinter, threading, unittest, weakref, xml, xmlrpc
there are also things like ord and chr I don't really see a need to be builtin (maybe in the string module) but they're used a lot in teaching
They're often used to construct a repr message, and they're widely used in tests to account for the lack of assertIs in unittest
hi is there any python package or module which gives information about the package present in the Pypi repository ?
using Pypi endpoints ?
Most of my uses of id would probably be one off scripts or the repl
or it need to be created ?
Wait, why does it do this?
because of some allocation strategies, as chilaxan described below
It guarantees that every object will get an unique id at the time it's called, but as it loops the objects get dereferenced and can be reused
what do you guys think about me jumping into this
https://getstream.io/blog/realtime-chat-django-angular/
what is more "correct" when implementing protocols, typing or collections.abc?
@lone trench I think it's off-topic spam personally
thanks
The latter since as I understand, the former has been entirely superseded by it in 3,9
can you expand on that thought @charred wagon ?
I'm just paging through mypy documentation and they use typing everywhere instead of collections
Maybe they haven't updated docs yet.
Python docs mark all the typing equivalents of collections.abc as deprecated
It seems you should use abcs for the inheritance, but use typing for the params/returns
oh I see what you're talking about now
huh. I didn't know the abcs didn't support the generics syntax previously
Wernt they also removing typing in future python versions?
I have not heard of that
I don't think so. There are still valuable things in typing
you can't create "true" generics without typing
Ah no they were removing the typing generics like List, Dict etc...
that's going to be a hard habit to break (from typing import List, etc.)
Yh
especially since we don't even have access to 3.9 internally yet 😢
we just barely got 3.7 lmao
Also waiting for the questions like why does list[foo] work but xyz not
Redesigning gradual typing in Python 4 
or maybe people will just give up on it and just let third-party type checkers parse comments with type hints
implementing strict static typing in Python 4 
Python 5 
Python 6 ⚙
sounds like python 2
mypy already supports type hint comments
Alot of linters can parse doc string typings tbh
type annotations came around because of the type hint comments of mypy
it's a shame they took so long to come about. TypeScript exists because of jsdoc in a lot of ways
Speaking of type hints... it seems to me that different type checkers (mypy/pyright/pyre/...) are not really compatible with each other. When you try a different type checker or try your type checker on an existing project, you get lots of type errors
Yep.
...because each type checker interprets the PEPs with its own interpretation
and e.g. pyright has recursive type aliases, while mypy doesn't
that hasn't been my experience and I flip between intellij/vscode pretty often (mypy v. pyre)
...and mypy treats Callables in class attributes weirdly
doesn't PyCharm have its own typechecker, not mypy?
or are you using mypy on its own?
It's my understanding it uses mypy under the covers. I use mypy in my CI as well
ah, pyright is the other thing I use, not pyre (via pylance)
the one thing I find unbearable about pycharm/intellij is its use of pep8 instead of letting me specify a linter
I recently tried pyre on my small project instead of pyright, and it gave me dozens of errors 👀
yeah, never used pyre so can't speak to that
👀
unexpected behaviour with other librararies or just unexpected behaviour which wouldn't happen if you didn't use it
idk seemed hacky
Well, you're just making a wrapper for an object
You're not mutating the actual module object
is top-level await allowed in py37? or do I have to use asyncio.gather or something?
I'm already using aiohttp; don't want to add another deps for one call
Huh?
If you're gonna start an event loop and use it youlo need asyncio or trio to actually start and run the event loop
Only certain repls like ipython support awaiting dorectly in the repl
Yeah, top-level await doesn't make sense, because await isn't tied to a particular implementation of an event loop.
Yeah, top-level await doesn't make sense,
(apart from repls)
Writing your own event loop 
@grave jolt plz
Sorry for the targetted ping but on mobile with dms off so modmail is 😩
!ban @unkempt rock spreading malware
:incoming_envelope: :ok_hand: applied ban to @mellow cedar permanently.
thanks
pban next
is the link somewhere else?
no
good
Erm
I have the file already
same
Theres another dude...
its the same thing as last time
:incoming_envelope: :ok_hand: applied ban to @soft tundra permanently.
you can yeah
Conceptually, what await does is ask the currently running event loop to suspend the current coroutine and run the need runnable task. You can't do it at the top level because there's no event loop to yield to at the top level
asyncio.run() creates an asyncio event loop and runs the coroutine using it.
yep, and if you decide to use e.g. trio, you're in trouble
There are other types of event loops that you can create instead, but the asyncio one is the only one that ships with Python
One thing i did learn with trio
my use-case here is avoiding adding requests to my dependencies when I already have aiohttp
is that its is depressingly slow compared to asyncio in terms of its socket handling
I mean maybe consider httpx ig in that case so you have both sync and async requests in one (providing you dont already have aiohttp as a dep for some other module)
or use urllib 😉
well I need an async client since I make the requests in my web server request lifecycle
my whole architecture is built around being async since most of my app is interacting with DBs and other web services
okay, but do you have like an explicit dep on aiohttp or can you use an alternate client 🤣
aiohttp looked like it had better support than httpx
I had an explicit dep on aiohttp ^
not that I need it, but I did have a need for an async client
Httpx Is fairly nice and a bit more sane than aiohttp
I mean sureee
Things tend to move straight from beta to abandoned, heh
But its in quite a late beta now and mostly due to the http2 support
"we should be 1.0 in late 2020" hasn't happened, so even more 👀
I work for a large financial institution, they balk at non-production-GA dependencies
For lots of projects, beta means "I'm still changing this", and the next stage after that is "whatever I give up it works"
Tbh idk why im pushing httpx cuz not like i use it any more than aiohttp
after the fresh hell I went through on Connexion and how it got included on the OAS 3.0 generators, I look at community contributions before I trust individuals or single companies
ig the biggest pull for httpx is the http2 support
what does Coroutine[T] signal to an API consumer, that T is the return type if you await?
since async signals the fn returns a Coroutine, right?
Typically its Coroutine[Any, Any, T]
:head spins:
because it follows the generator type pattern
you spoke past me with that one. mind expanding?
Well coroutines are built off the idea of having a generator with yield that lets you suspend that function
the generator can yield a different type to what it returns
but it can also have foo.send(x) called on it to wake up where it yielded from and return the value from it yield
so you have a yield type, return type and send type i think
You may want to use Awaitable instead of Coroutine. Then it would just be Awaitable[T] to signal that calling await on it returns a T.
honestly cuz the community that built it dont really have much of an idea either
Some of the confusion thats happened in the past in the community is 
"nodejs is great, let's copy it!" "wait, how do eventloop?"
my biggest peeve is the streams api
of all the async APIs I know, I like .NET's the most
the Task<T> is so easy to understand
asyncio has improved a lot... 3.7 was a massive leap forward over 3.6 in terms of providing higher level interfaces that people can actually understand.
Unfortunately, all the low level stuff is still there, and it's still possible to find the wrong stuff...
Trio is the 'sane' version of asyncio
the only issue with trio is the speed
in the sense that it is really slow in the areas where async should excel
like i/o resources?
mhmm
like waiting for socket readiness etc...
instead of the callback approach which tbf is probably the best part of asyncio and actually really well implemented in terms of efficiency, they use a fixed awaitable that only awaits once then you have to await again
I think my biggest disdain about python is its use of functions over interfaces
like len() map() etc
an __iter__ should be able to use a map postfix
you mean the fact you have to call a function that just calls another function 
yeah
give pipe operator
how would that even look
my_iterable
|> map fn
?
I guess we'd either need a way to pass multiple arguments or create partial (curried) functions
iterable |> functools.partial(map, int) is not really making it better, perhaps *(func, iterable) |> map?
Fair enough
Well, that's not just an alias for a method. iter also works if your object defined __getitem__. Although... that's not a particularly frequent use case, I guess.
But composing iterator functions is a pain, yeah
I've been writing a lot of Rust over the past few months in my free time and coming back to Python gets worse each time 🤷
foo
.iter()
.map(...)
.filter(...)
.flat_map(...)
.to_list()
yeah^
if __iter__ exists, you should be able to just call .list() imo
in addition to the other iterator methods
but that's probably a pretty big breaking change
The difference between Python and Rust is that Python doesn't have much static information at all, so all available methods need to be placed in the definition of a class.
I guess you could inherit from Iterable...
oh I'm aware, it just makes me sad
so say I'm writing an async function, what's the most appropriate annotation for its return type?
Awaitable[T]? since that's the only intended use-case is to await on it?
I notice a lot of libs just ignore annotating async fns entirely
async def foo(bar: A) -> B:
...
# <=>
def foo(bar: A) -> Awaitable[B]:
...
hm, interesting
The coroutine function's return type should just be as normal
gotcha
@desert peak (not really, the return type should be Coroutine https://docs.python.org/3/library/typing.html#typing.Coroutine, but Awaitable is good enough for most purposes)
but yeah, Awaitable/Coroutine would just be redundant in async
Also @desert peak if you want an exercise, make two functions to transform between Iterator[Awaitable[T]] and AsyncIterator[T] 🙂
nah, I've got work to get done 😄
Iterator[Awaitable[T]] -> AsyncIterator[T] is easy, the other way around -- not so much
there's a hacky implementation here <#async-and-concurrency message>
it's a shame yield from was removed from async fns
could've eased that implementation some
I'm not entirely sure on the reasoning
@desert peak Iterator[Generator[T, S, R]] <-> Generator[T, S, R] would look pretty much the same
I think it'd be cool to see a Rust implementation of Python. I think it could benefit from its ease of development for new features
Though it'd be wildly unpopular with the existing developer base
RustPython is a thing iirc
pyo3, but it's not actually a Rust implementation of Python
it's for developing new extensions instead of C
Rust Python is a thing indeed
We're also slowing making progress to adding some better support for async and await stuff in PyO3 although the system is a lil naive atm
Rust python may also become the first python interpreter built around the idea of what numba's JIT does with LLVM but with cranelift
oh so rust python is already a thing people are working on?
what's the benefit of the cranelift backend?
Well CraneLift is a much faster compiler
Which will eventually become rust's debug compiler
But the general aim of RustPython's JIT is to allow the entire Python system to become JIT compiled making use of CraneLift's speed
I think RPython would've been a catchier name akin to CPython
does that mean RustPython would ship with cranelift's compiler?
to accomplish the JIT?
Well the Jit contains cranelift itself
Atm the standard none JIT system of RustPython is a little slower than CPython atm
but ig thats to be expected as its no where near as optimized as it could be
no releases since Jun'20 makes the project look dead
think 1.2 was the first semi stable release with out the std lib
yeah
not really something you'd use for production rn, they're just slowly building the std lib up
So today for example introduced a bunch of unit tests for implementing the random lib
aim seems to mostly be implement unittest properly so they can start using Cpython's test suite
btw
obvi (on non-prod rn)
did you know its possible to override the coroutine wrapper?
I haven't used any asyncio prior to adopting FastAPI at Q4 last year. Never really had a need
that logo...
rip
Oh i see now
I imagine the hardest part is just getting the execution model and grammar correct, no?
I partiality updated my branch due to conflicts 
so im missing like
600 commits
time to delete and re-clone ig
I think their compiler infra (parser, lexer, compiler) is decent enough
if you guys had a coworker who makes the worst APIs you've ever seen and hasn't improved in two years, how would you even begin to handle that? Just ran into one of the dumbest issues I've seen this week where a required attribute goes uninitialized intentionally
which breaks downstream
I've contributed very little in the past, though it is really hard to just keep hacking on it. not really relevant with the project but rather rust is a bit annoying in terms of compile speed
Rust's particular setup with LLVM seems to like high clock speed
My PC with 6 cores at 5ghz will beat my server running 16 Cores at 2ghz
hm, rustc seems to use all my cores at full utilization just fine
Alot of it is affected by the compiler config in the toml
hopefully alot of the issues with compile speed for debugging will be fixed with cranelift when it eventually becomes stable
but won't that cause subtle differences between profiles?
if you use rustc backend for release and cranelift for dev?
I mean yeah but you shouldnt be using debug to bench stuff anyway
debug mode can quite literally be between 10 - 100x slower than release mode
I see
oh, cool!
@true ridge are you a maintainer for anything CPython or a contributor alone?
I ~maintain the AST interface. We dont really have a maintainership / subsystem concept, but rather (not official) zones (codeowners)
is there any excitement for Rust among CPython devs?
AFAIK there are some people who are really interested in Rust, and pyoxidizer
I also want to start writing it, but like as I said, it really annoyed me with high compile times. If it will be improved in the future, I don't see a reason to not to write rust
I think that's one of their big goals with ed'21 is a better const story which should help compile times
the improvements of Rust since 1.0 have reminded me a lot of C# improvements in the same timespan now with Nadella at the head. It's like we entered this super developer-focused timeline after the stagnation of the 2000s
I suppose Python also fits in that boat with py27 finally gone and people actually moving their packages forward
i agree for the most part
do feel like python's async system is sorta stagnating though
Well JS is a JIT compiled lang and also has alot of semantics that allow it to not have the same sort of hurdles as python does
equally everyone who's really maintaining python is doing as a volunteer and unless someone feels motivated enough to try improve the performance it wont get much better
I personally wouldn't want to try optimized Python's C code base 
JS is jitted? By what?
Wdym by what
its entire implementation is built around a JIT compiler and a async runtime
I didn't know V8 JITed.
IIRC i believe all runtimes for JS are built off a JIT
JS as a language is alot younger than Python as well as it's runtimes so it was able to learn alot from python's mistakes
95 was the original version
JS did see new life with nodejs and Google investment with V8
But bearing in mind JS went though the massive re-design and re-implementations that lead to V8, libuv etc....
what was it called again bow
ES6?
?
the JS language spec thats used now
I really have a hard time believe JS beats Python benchmarks.
You should believe it
it's public info... it beats it handily
JS is wayyyy faster runtime wise
Async by default + incredibly fast development in it's libs
I wonder how it compares when you use something like numba.
wont change much if at all
Clearing a JITed language has it's advantage.
well yeah
Sadly Python's asyncio basically kill's PyPy's advantage
also if you look at these sorts of benchmarks https://www.techempower.com/benchmarks/ to judge the speed then your performance is entirely dependent on how well a framework pipelines
If you ever wonder why Japronto is so much faster than any of the others
Its just because Japronto pipelines
all the others just queue
?
?
I don't understand what pipelining means I guess
oh gotcha
So the client sends many requests before getting the first response back
the only issue was that servers never really behaved properly, along with DNS issues etc... and HTTP/2 came around
so basically all of those tech empower benchmarks are pretty much entirely un-realistic as your clients will never really send pipe lined requests
too bad http/2 support still suffers
disabled is all modern browsers
it's coming around - very slowly
speed rarely matters for most projects, however
people doing pre-optimizations picking the wrong tool for their job
I personally like Rocket from an ergonomics perspective
because it has a complete HTTP spec coverage as well as a the work stealing tokio runtime
I want to make the case for Rust at work, but I think my scaffolding cli will have to do for now 😅
I preach the work stealing runtime for everything where its good for it lol
Websocket gateways are just
I want to implement Http2 for my rust server but yikes the amount of info on it is not nice to try make
Basically HTTP/1 pipe lining but sane
My aims atm are:
- Finalizing HTTP/1 ASGI stuff
- Writing the WS protocl
- Adding HTTP/2
fun times
I wish there was a rich-like cli lib for Rust or tqdm
Python has so many nice libraries
I'm looking at clap v. structopt rn
they look like they implement the same API so I'm unsure which to use
but clap has major versions?
Claps always done me good
because classes use the module level scope for some reason
not the local scope
its weird
but why does y = 1?
works as expected here: #bot-commands message
Yeah I tried that too
I think I kind of get it. Any changes or reassignments to certain module level variables will make them be module level regardless (as long as inside the class)to the position of the change or reassignment?
!e Interestingly enough
x = 0
y = 0
def f():
x = 1
y = 1
class g:
print(x, y)
x = 2
print(f.__code__.co_varnames)
@brave badger :white_check_mark: Your eval job has completed with return code 0.
('x', 'g')
I guess, it was itneresting to look at, however, if this is actual problem, it sounds like software design issue
I don't know, more I look at it, y , confuses me too. X makes perfect sense
as the helper mentioned, maybe it is because the value of the x is changed but y isn't
I mean I can understand what's happening but I've no idea why it's designed that way
https://docs.python.org/3/reference/executionmodel.html#binding-of-names
If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal or global.
https://docs.python.org/3/reference/executionmodel.html#resolution-of-names
Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace.
So - the assignment to x inside the class g makes x a local variable for that block. When the x is resolved at the time of the print, the local x variable is unbound, so resolution falls back to the global x variable, which is 0.
Meanwhile, the y variable isn't bound inside the class g block, so it isn't a local variable, and so it follows normal resolution rules:
When a name is used in a code block, it is resolved using the nearest enclosing scope.
And that finds the nonlocalythat's set to1in the scope of the enclosing function.
So in a sense, you cannot have anonymous classes?
the first argument to the type constructor is a name, so no - every class has a name.
Though, weirdly, it's allowed to be an empty string.
!e ```py
C = type("", (), {})
print(C())
print("Name:", C.name)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | <__main__. object at 0x7f569692dfd0>
002 | Name:
Can u print dir(C()) too?
!e ```py
C = type("", (), {})
print(vars(C))
print(vars(C()))
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | {'__module__': '__main__', '__dict__': <attribute '__dict__' of '' objects>, '__weakref__': <attribute '__weakref__' of '' objects>, '__doc__': None}
002 | {}
vars is probably more interesting than dir.
I mean, anonymous in the sense that returning a function is creating anonymous function
yeah that works
def myfunc():
def _anonymousish():
pass
return _anonymousish
changing anonish to a class should work the same way
But the scoping is messed up
As of now anyway
I actually like Ruby's closure thingy. I don't think you can do something similar with lambda?
I'm not sure what you're getting at. That's not returning an anonymous function, that's returning a function named _anonymousish. And you can use the same technique to return a class that's created dynamically.
returning a function isn't creating an anonymous function
that would be lambda
and the analogue (kinda) would be creating a class with type
if you were to think of "anonymous" in the sense of "anonymous function", then such classes would qualify as anonymous, IMO
It's as close as you can get, at least.
heh, you can also do:
!e ```py
def foo():
return type("<lambda>", (), {})
print(foo())
print(foo()())
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | <class '__main__.<lambda>'>
002 | <__main__.<lambda> object at 0x7f107c8cbfa0>
I thought class declaration uses the module scope instead of function scope?
Or is it just a bug in the current version?
no, that's not what's happening. Read the docs paragraphs I pasted again.
What you're seeing there is a quirk of class bodies, as opposed to def bodies - when something would result in an UnboundLocalError if it were done in a def body, doing the same thing in a class body results in a lookup against the module globals instead.
Oh, okay. That's actually reasonable.
but given that the same thing would be an error if you did it in a def, it doesn't have anything to do with whether it can be used for closures.
I'm betting the reason for that quirk is to allow you to do things like:
SOME_CONSTANT = 42
class C:
SOME_CONSTANT = SOME_CONSTANT
that is, it gives an easy way to re-expose module globals as class attributes.
I can't do something like this tho...
def a():
x = 10
class A:
x = x
return A
print(a().x)
Oh wait, using other names for the class variable (i.e. not x) works fine
you need to do a()().x
no, you don't - it's a class variable.
!e fwiw, you could also do that using the type constructor. ```py
def a():
x = 10
return type("A", (), dict(x=x))
print(a().x)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
10
I'm thinking about those Java callbacks with anonymous classes
those are usually written as lambdas instead, in modern Java
Yeah
they were only ever classes because Java didn't used to have any way to pass a function around, only a class instance.
(That's the case for a lot of design patterns - many of them are just workarounds for limitations in the Java language)
Singleton is the classic example - it's a way to create a global variable in a language that doesn't allow global variables.
Yeah
Now that I think of it, this is pretty useless lol
def a(x):
class A:
def __init__(self, y):
self._y = y
def get_value(self):
return x + self._y
return A
print(a(10)(11).get_value())
Maybe useful for programmatic class declaration, code generation?
🤷 functions that create classes aren't necessarily useless.
Yeah, that's probably the best use case for it.
or possibly class decorators.
Yeah
Singleton is the classic example - it's a way to create a global variable in a language that doesn't allow global variables.
Singleton is usefull if you're writing a library and want to prevent the user from making duplicate instances of a class, if there can only ever be a single instance of it but it has to be user made
but how often does such a class exist?
or to work around circular imports since you can import the class instead of the instance
i mean i've had the need like, 2 times in a few years
its definitely not common but saying there is literally no need since we have globals is just wrong
I feel like most of these cases could be replaced by a module or something like SimpleNamespace
you cant instantiate a module with say, a API token.
and im not sure how SimpleNamespace would help that either (tho i have to admit this is first ive heard of it)
I guess if you need global state which needs outside data which it cannot load itself (for example the data needs to loaded late in the loading) and it needs more complex logic rather than just being a mapping of attributes to values then there is value in making a singleton. So ye, IG there is merit to the pattern.
now, i will admit that i did implement and publish a library for multitons without knowing any use case lmao
Hey
Sorry for disturbing
Python 3.9.1 is not working properly
How do you make colored text like this ?
I wound many Bugs and its Totally hard to use it
The python is not working in the terminal
the command python in terminal is not working
Just see this
I want to switch on 3.8
But show any one
Please help me
@twilit zealot @unkempt rock this is not a help channel; see #❓|how-to-get-help
You can implement that without the singleton pattern. I would do it with a global variable initialized to None and a function that initializes that global if it hasn't been already, then returns it. And that's not the singleton pattern, though it's a different way of creating a singleton object.
That is, the singleton pattern refers to a particular way of creating and guaranteeing that only one instance of a class will ever exist, designed around the limitations of a language without global variables
Are there times you can think of when defining a new singleton class in Python makes sense?
Depends what you mean by "singleton class". Are there times when it makes sense to make a class where only one instance should ever exist? Sure. Are there times when I would use the singleton pattern to accomplish that? No.
I'm referring to the latter, where deliberate construction returns the same object.
That's not the singleton pattern, either. The singleton pattern has a private constructor and a public getInstance method
Though I wouldn't do either of those 🙂
it's even worse than I thought...
I've occasionally used the monostate pattern, though. I like it better than singleton: rather than restricting that only one instance can be created, it allows any number to be created, but all of the class's state is stored in class variables rather than instance variables, and so an update made through one instance is visible through all the others.
when have you used that?
I can't remember a particular case, but you could imagine using it for logging, for instance. As it works today there logging.getLogger(name="") which looks up an existing logger with that name, and creates one of it hasn't already been created. Instead, it could create a brand new LoggerImpl object (a monostate that the user has configured), and each time it wants to log something it could pass the name along to instance methods of the LoggerImpl, which handle it according to the configured class state. Or something.
Caches are another good example. You could imagine an HttpCache that would use the monostate pattern to encapsulate responses cached by request as class variables, and anyone who wanted to see if something has already been cached would construct a new HttpCache and call lookup(url) on it, and - since it shares state with every other HttpCache that has been created, that'll work
are you absolutely sure that's what a singleton is? AFAIK is just a class where only one instance is possible, not specifically that.
Well, https://en.m.wikipedia.org/wiki/Singleton_pattern - certainly as described by GoF, it refers to a particular design with a private constructor and public getter.
look at the implementation section, the private constructor and getinstance is listed as a typical implementation, while the actual implementation only has to
An implementation of the singleton pattern must:
ensure that only one instance of the singleton class ever exists; and
provide global access to that instance.
Well, 🤷♂️ - what do you think the word "pattern" means in "singleton pattern"?
I think it refers to an approach that can be taken to create objects that are singletons.
And I would argue that other approaches to creating singleton objects are not the singleton pattern.
okay so, wikipedia agrees with me. every otger resource I've ever seen about singletons agrees with me. if you want to follow your own definition by all means go ahead but that will make communication vastly more difficult
Is a module level _STATE = {} in Python a singleton object? Is it an example of the singleton pattern?
is it a class? no. looks like a dict to me which is a instance of the dict class.
and has no way to ensure onoy one instance exists
hence: no singleton
Well, if your definition is that there's a guarantee that only one instance ever exists, then it's not possible to create a singleton in Python.
its not about a absolute guarantee, you can always monkey patch your way around, but about normal usage, like instantiating a class with a constructor, returning the same instance
if you want to look at dictionaries specifically i would argue they are more like multitons, since the same arguements return the same instance
How about ```py
class MyState():
pass
MY_STATE = MyState()
del MyState
Is that a singleton object? Is that the singleton pattern?
the fuck
!e ```py
class MyState():
pass
MY_STATE = MyState()
del MyState
print(id(MY_STATE), id(type(MY_STATE)()))
@finite sparrow :white_check_mark: Your eval job has completed with return code 0.
140708913422288 140708913422240
doesn't look like a singleton to me
hiding the constructor is not something i would consider a singleton, though that's more arguable then whether a singleton has to be specifically the Java implementation
You've moved the goalposts, I'd say. A minute ago you said it's about "normal usage", and then you took an object, called type() on it, and called the resulting class - that's not normal usage for an object.
hmm, again as i said that's something I'm not so sure on, even though i think type() is normal enough ymmv
calling type to check the type of something is pretty normal, but calling the resulting type isn't common.
fair enough, in that case yes you could say that's a singleton, though when doing it like this there truly is no advantage
And the WIkipedia implementation of a Python singleton is py class Singleton: __instance = None def __new__(cls, *args): if cls.__instance is None: cls.__instance = object.__new__(cls, *args) return cls.__instance But you can get another instance of that class as easily as doing: ```py
new_inst = object.new(Singleton)
that's not any trickier than calling type(), I'd say.
all the advantages i can think of rely on the fact the instantiation can be done elsewhere
as i said, fair enough
the Wikipedia implementation is one that i would consider since it allows for instantiation elsewhere
well, so does this: ```py
_MY_THING = None
def get_my_thing():
global _MY_THING
if _MY_THING is None:
_MY_THING = _create_my_thing()
return _MY_THING
at that point were talking about the usefulness off specific implementations which depend on the specific requirements
I don't think we are, still - because I don't agree that that's an implementation of "the singleton pattern"
though it is a way to create a variable that is intended to only ever be created once during the program's execution.
and as i said, every resource i found disagrees with you, this is becoming pointless.
the singleton pattern, as described by GoF, is summarized on that Wikipedia page:
The singleton design pattern describes how to solve such problems:
Hide the constructor of the class.
Define a public static operation (getInstance()) that returns the sole instance of the class.The key idea in this pattern is to make the class itself responsible for controlling its instantiation (that it is instantiated only once).
The hidden constructor (declared private) ensures that the class can never be instantiated from outside the class.
The public static operation can be accessed easily by using the class name and operation name (Singleton.getInstance()).
If you're arguing that "the singleton pattern" is broader than what the GoF called "the singleton pattern", then fine. But what you're describing is not what the people who coined the term were describing.
if other resources have made up their own, different pattern, and then said "and this is also the singleton pattern" - well, there's nothing I can do about that, but now there's two patterns instead of one and the same name is being used for both.
If only one instance should be possible, why not implement it as a module? Unless you're doing some importlib hackery, there's only ever one instance of a module.
the "constructor" can also automatically disappear
FWIW that doesn't take importlib hackery, it's enough to do:
import foo as lib1
import sys
del sys.modules['foo']
import foo as lib2
ah, well, yes
it's so easy to do that sometimes people do it accidentally. import foo after running python foo.py...
alright - considering our disagreement over what does and doesn't constitute "the singleton pattern", I'll amend my thoughts above: since in Python it's impossible to create a class that can only be instantiated once, you may as well just use module-scoped variables, possibly lazily initialized.
we can disagree about whether it's a limitation of Java that necessitates the singleton pattern or a limitation of Python that makes it unenforceable, but regardless of which of those two it is, there's not much point in using it in Python.
i'm kinda glad i missed the singleton debate 🙂
you won't believe how many interpreted vs compiled discussions you've missed
why not both?
both discussions, or both compiled and interpreted?
not sure what you mean in either case
python is both compiled and interpreted - and, referencing the "why not both" meme 🙂
usually whenever it comes up someone ends up going "well aaaaaactualyyyyyyy"
It's the quickest way to end the pointless discussion, heh
Compiled? You mean compiled to bytecode?
Yes. CPython compiles Python code to CPython bytecode, which it then interprets.
Is there a way to delete an object but not destroy the variable?
Like
a = SomeObject()
...
if some statement or otherwise:
del a
...
if a is None:
print('No value')
does a = None work? Also this sounds like something for a help channel
I just wonder if Python has similar mechanism to like C++
The object would be GC'd if the refcount drops to zero
Python's names are different to that of C++'s in the sense that there's no "uninitialized" state to them
Names in Python reference some object in memory, whether it'd be an arbitrary object or None
So the most efficient way to delete objects are like this?
value = receive_some_object_from_function()
value = None # garbage collected
I assume setting to _ won't actually delete the object
del value or value = None will both drop the reference to the object that was held in value, and that may make the object eligible for garbage collection if there are no other reachable references to it.
Well, you don't really have to worry about it too much in Python; however, if your use-case really needs it, then you can use weakrefs to make sure that you're not creating any rouge references to a resource
And, while both del value and value = None drop the reference to whatever object was being held in value before that, the difference is in what value contains afterwards.
With del value the variable no longer exists, and you'll get a NameError if you reference it.
With value = None it still exists, and holds a reference to the None object.
Hmm, okay
value = 42 would work just as well to drop the reference to whatever object you're done with, and replace it with a new reference to an int object with the value 42.
can someone tell what is the difference between pythonfire and argparse ?
are they both same or they have different use cases?
>>> type.__class__
<class 'type'>``` hmm, how does this even work?
and that could go forever like, type.__class__.__class__....
type is defined in C, so I guess it actually is an instance of itself
I believe it's because of the fact that primitive (meta)classes themselves aren't actually Python classes, but are implemented in such a manner that they're indistinguishable from normal Python classes when used in Python code.
If it quacks like a duck, it's probably a duck[, even if it's not]
You can see that it is implemented in C due to the operator overloading signature
!d type
class type(object)``````py
class type(name, bases, dict)```
With one argument, return the type of an *object*. The return value is a type object and generally the same object as returned by [`object.__class__`](stdtypes.html#instance.__class__ "instance.__class__").
The [`isinstance()`](#isinstance "isinstance") built-in function is recommended for testing the type of an object, because it takes subclasses into account.... [read more](https://docs.python.org/3/library/functions.html#type)
oh
Would there be a way to actually make everything consistently act as objects, even with primitives?
everything does act like objects
Hmm, yeah... 🤔
oh yeah, though i thought there was some magic methods like __add__ or something which would let us do that?
I don't think this is a thing yet
how would you imagine that working? type hints aren't really consistent enough to make this possible
Eeehh.. First level typehints could work
Someone paste the docs for typing.overload here
!d typing.overload
@typing.overload```
The `@overload` decorator allows describing functions and methods that support multiple different combinations of argument types. A series of `@overload`-decorated definitions must be followed by exactly one non-`@overload`-decorated definition (for the same function/method). The `@overload`-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-`@overload`-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling a `@overload`-decorated function directly will raise [`NotImplementedError`](exceptions.html#NotImplementedError "NotImplementedError"). An example of overload that gives a more precise type than can be expressed using a union or a type variable:... [read more](https://docs.python.org/3/library/typing.html#typing.overload)
That's a misleading tutorial
then you need ambiguous call errors and other such silliness
hmm
that is not quite right
Maybe Python is biting more than it can chew with overloading
but it is close enough for most things
Imagine Python 4.0 coming in with a strict mode that enforce typing lol
What about defining custom operators 
!pep 638
we are slowly getting closer and closer to raku
using metaclasses, you can overload bound methods within class bodies but it doesn't work with dunder mathods from my experimenting (and linters really don't like you doing it)
I made this, but as you can imageing, the implementation of the metaclass is very hacky (and idk if the logic beind the overload is consistent with other languages, just how i thought to implement it)```py
class TypeOverloaded(metaclass=TypeOverload):
var = "some var"
def foo(self, x: int, y):
print("foo (int, Any)")
def foo(self, x, y: str):
print("foo (Any, str)")
def foo(self, x: int, y: str):
print("foo (int, str)")
cls = TypeOverloaded()
cls.foo("abc", "def")
cls.foo(1, 1)
cls.foo(2, "abc")
print(cls.var)
foo (Any, str)
foo (int, Any)
foo (int, str)
some var```
brm
¯_(ツ)_/¯
Interesting
anyone know if any editors support generation of protocols via type annotations yet?
like if I had class T(Iterable[str], MutableMapping[str, str]):, to see __iter__, __getitem__ and __setitem__ implementations with correction annotations?
at that point i think its getting past the point in sane typing
why do you think so? that's a normal case in other languages
Yeah for static languages sure, but atleast imo, python's dynamic typing generally makes it just a lil, unatural
if I implement an interface for a type in other languages, the editor handles all the boilerplate work of generating their methods for me
but again im not someone who massively strict types in python
I type what i need to enough for it to be easy to understand not enough to enforce constraints
i find having a mess of typings everywhere is arguably harder to maintain but 🤷♂️
until you run into a logic bug because you didn't annotate that static analysis could have found 🤷
I heavily use the pydantic package these days
Python, while fast to develop in, was not my choice of language but it beat being forced to use Java
were can we learn python?
!resources #python-discussion
The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.
Do you consider that object-oriented programming (OOP) facilitates the resolution of a problem or
need, identifying the actors that participate with their respective actions?
I have no idea what you're asking, but it's irrelevant to this channel. Try #python-discussion
that sounds like a test question
._.
Help me
Okey...
Do you think that the OOP method facilitates the resolution of a problem or
need?
No. You are in the wrong channel.
that is defo a test question
It isn't, it's just a class question
I doubt that
no one casually words things about OOP like in anything other than test questions
well class question sure
^
in general people don't talk about OOP like that except in academics
???
but still a school work question
!rule 5
5. Do not provide or request help on projects that may break laws, breach terms of services, be considered malicious or inappropriate. Do not help with ongoing exams. Do not provide or request solutions for graded assignments, although general guidance is okay.
Time for you todo some bop bop research on your own™️
regardless, this is not the channel for that discussion
But I don't know what to answer, because I never understood this method.
Then ask the teacher :P
Or take an help channel, it is explained in #❓|how-to-get-help
Give me coalesce operators and eff'ing builtin multiple dispatch. I feel like if type annotations got fully fleshed out to consider everything then multiple dispatch would be an ez extension.
None-aware syntax does have a RFC, but I'm sure someone has already argued against it for some reason
"syntax purity" or some other nonsense
https://www.python.org/dev/peps/pep-0505/
found it - deferred for some reason
wow, 2015 proposal. someone was a forward thinker
would be nice to have tbh
the python purist types say "just try it and use try/except everywhere"
!e
a = 'str'
try:
v = a.b
except (AttributeError, NameError):
v = 'default'
You are not allowed to use that command here. Please use the #bot-commands channel instead.
I wish more of the grammar was an expression vs. statement
you can just use a generator-based contraption
like do notation, but in Python
I think I can find it somewhere
you lost me at "contraption"
that's hideous and does not communicate what null syntax does
yeah, that's pretty esoteric
it's basically copied from functional languages (haskell/scala/f#) where you can do this
readFromConfig :: Config -> Maybe (Int, Int, Int)
readFromConfig config = do
foo <- lookup "foo" config
bar <- lookup "bar" config
baz <- lookup "baz" config
return (foo, bar, baz)
and it is translated to a callback chain
readFromConfig :: Config -> Maybe (Int, Int, Int)
readFromConfig config =
lookup "foo" config >>= (\foo ->
lookup "bar" config >>= (\bar ->
lookup "baz" config >>= (\baz ->
Just (foo, bar, baz)
)))
Speaking of esoteric, here's another blast from the past:
class CustomOperator:
def __init__(self, func):
self.func = func
self.lhs = ()
def __gt__(self, other):
if self.lhs:
lhs, rhs = *self.lhs, other
self.lhs = ()
return self.func(lhs, rhs)
self.lhs = other,
return True # Must be truthy to eval both parts of chained comp
def __call__(self, lhs, rhs):
return self.func(lhs, rhs)
nullnt = CustomOperator(lambda x, y: x if x is not None else y)
print(None <nullnt> [])
print(0 <nullnt> 'hello')```
hehe
my brain D:
have you seen <#esoteric-python message>?
has anyone done monads in Python that look nice yet?
I think there was a package that did the same thing as this CustomOperator, except... not poorly
async/await 🙂
one thing I regularly miss from Rust are Option<T> and Result<T, E>
python doesn't do postfix, does it?
yeah, just prefix
and infix
Although you could consider a method call a postfix operator.
foo.bar() instead of the prefix bar(foo)
I found out that Generic[T] syntax is generally supported in Python. I wonder how I could use that to implement Option/Result types that are ergonomic
I guess subscripting is also postfix-ish?
yeah
and calling -- if you consider calling as an operation on a function, not on its arguments
I wonder if I could make a generic constructor... if T[R]() would be valid syntax
that is valid syntax
then I wonder how I would access the R from the constructor
You'd return an object that somehow binds R
borderline esoteric for python lol
You can surely access some dunder, I don't remember which one
you'll have to scavenge in the REPL
But, of course, you'll have to write it out explicitly
if you want this kind of type stuff, Python is probably not the place to go
!e
class A:
def __class_getitem__(self, item):
class AInst(A):
generic = item
return AInst
def __init__(self):
print(self.generic)
A[int]()
@flat gazelle :white_check_mark: Your eval job has completed with return code 0.
<class 'int'>
nice, so I can create a generic and then assign the discriminator somewhere
What the heck is __class_getitem___, is that purely for typing
In general you'd code it in a way where your statictype checkers will infer the type
it's a new 3.9 feature which allows dict[str, int] as a type hint
Oh man, what if I have a custom meta where I implemented __getitem__?
Bc I do have a class registry that does that
I thought __class_getitem__ came before 3.9, it's just that built-ins didn't have it until that point
I made the unfortunate mistake of trying to cram advanced type stuff into Python way too many times. So the real advice is to maybe find something simpler.
I am not really sure actually
you can inspect the generic type as well
are you talking to me?
unfortunately Python has a way of doing that to you. it has all this potential, but what seems like a steering committee that's squandering it 🤷
It's present in 3.8, not sure about earlier versions
well... it's just that it won't be useful for most Python users
but it is valuable to the library makers that make content for most Python users
like the macros proposal
what happens if I have a custom meta with __getitem__ and then on my classes have __class_getitem__?
Calling the class with a type just doesn't seem all that helpfull when generics already work plenty fine when infered.
how would you find the inferred type of a generic for your class?
Say, if I had a tuple type
I'm not sure what libraries or what authors you're talking about -- many library authors are even hesitant to add type hints
I think that's largely because they were hanging onto py27 users
...although there are libs like numpy that would benefit from features like type-level integers
GvR was at the last pandas developer meeting specifically talking about type hints
"oops, that number is too big for c_int_u32! teehee!"
Dude I wish they implemented some sort of generics for array shapes
GvR?
Guido Von Rossum
pandas is absorbing the type sheds that microsoft has in some repo
isn't typeshed a mypy thing?
sure, but he's still widely respected across the ecosystem
sorry type stubs
ah, never heard of that before
Seems like a dependent typing rabbit hole... You can actually do something like type-level naturals (with peano numbers), but you can't add them (unless you do... lots of @overloads for array shapes, but then you can't make generic transformations like n(n+1) ~ n*n+n).
xref #28135 (comment) do we want to make pandas PEP 561 compatible? https://mypy.readthedocs.io/en/latest/installed_packages.html#making-pep-561-compatible-packages
I'm not saiyng make an argument validator but hints to specified size and shape would be aweomse see matlabs argument blocks https://www.mathworks.com/help/matlab/matlab_prog/function-argument-validation-1.html
Declare input argument class and size and enforce restrictions on argument values.
function out = myFunction(A, B, C)
arguments
A (1,1) string
B (1,:) double
C (2,2) cell
end
% Function code
...
end
So A should be a scalar, B some row vector, and C and 2x2 matrix
1-indexed lang
🤮
typical, completely miss the point because of your own vitriol
I'm not missing the point, I'm just making a joke. I don't have an investment in this particular conversation
I mean, there is no problem if want to implement that on your own. The issue is more that it is less flexible than if - raise, and quite a few functions on arrays have quite complex preconditions
I think it would be an amazing addition to numerical related libraries. Very often people could write functions expecting data to be in a certain shape and stuff will go very wrong if its not oriented in that but still run completely, error free.
Rust is going through a similar problem with generics and array types atm
more specifically, const generics
you need dependent typing for the kind of safety you would want, which is really complex and not ready for general use.
from the discussions I've seen about that, it is a difficult problem
How did matlab do it so easily for their objects?
they only provide very basic checks
I guess thats a dumb question because theres a lot of stuff in python that doesnt exist in matlab but at least from numpy's perspective
like most functions don't need a 3x3 matrix, they need a square matrix
a square matrix is still possible, but not everything is
I don't think this is useful enough to provide sugar for in the general case
and well, you could make a decorator that parses these preconditions from a docstring if you really wanted it
so off-topic from the whole generic arrays convo
can anyone explain why python sees an empty dict as falsey?
bc the length of the keys is 0
is it because it's a collection type?
so if I implement Sized for my T and it returns 0, python would see my T as falsey as well?
if __bool__ isn't implemented then the output of __len__ is used. Any nonzero integer is True and 0 is False if neither __bool__ nor __len__ are implemented then the result is automatically True.
thanks for explaining that. I knew what types return false, but wasn't sure on why
that's like the 4th time i've explained it and have I have the definition of __bool__ almost seared into my brain now lol
since JS is a different beast
and I work in a few languages that all seem to have different semantics
it creates an issue in etree, where every node is a collection of its children and it's len is the amount of children, but also .find returns None of no element is found. So you need to explicitely ask
its quite the annoying trap
glad I haven't needed XML recently
I'd say interpreting values as booleans is a bad idea anyway
sometimes you just want easy conditions
idk why, but if not list: just... doesn't work for me (compared to if list == []:)
in how many cases is it even correct to use interpreting as booleans
But then people have to wrap len to check if iterables are zero length
but what if u have some complex object that implements __iter__ and __len__ but can't be typed that easily.
Which is quite weird to anyone not used to python.
.is_empty()
or len(_) == 0
I suppose
Now that im used to it, I like it but it did take me a while to get used to it.
I don't like the implicitness of if not list:, and it can also hide bugs (e.g. if list is 0, None or something else)
static checkers would detect that
a lot of us hate typing though
I tried to use it but it quickly becomes too verbose
but here I am asking for array size type hints >.<
get out of here with that logic. if I had the option, I'd subclass all the collections to implement sane methods on them 😦
everything being a function drives me loony
I especially feel it in filter, len and map
Right, but some things are untypecheckable, so the typechecker can't find everything
only because of hacks with proxy types by library devs
Are you familiar with lenses (getters/setters on immutable data)?
you mean properties? or views?
I haven't heard "lenses" as a term before
first is a lens -- it's an object that describes how to get or set the first element of a tuple
tuple being immutable, that means a new type would be returned, no?
so (first * first).setter("b")(x) is like x[0][0] = "b", but for immutable data
new "object" that is
Yes. It's like a getter&setter, but "setting" means creating a new value
and you can compose them with *
The exact principles aren't important here,
the main point is that you can't give first or second any coherent type annotation besides Any or Lens[Any, Any, Any, Any].
no proxies or metaclasses involved
What would that mean? And, well, you can't do that

