#internals-and-peps
1 messages ยท Page 125 of 1
yeah, the issue is that slight patches to existing languages will rarely see much adoption, since they aren't enough of an improvement
crystal is the one that does best from all the projects I know of, and crystal is scary impressive
and yet, ruby is so much more useful than crystal is
well, i'm generally happy with the direction python is going, otherwise i wouldn't bother working on a crazy project like justuse ;D
yeah, there seems to be a real effort to improve things
better errors, more specific errors, patma, ...
yeah, but at the same time, backward compatibility (which is of course crucial)
kind of like a Java situation
yeah, let's not have py2 to py3 2
and java is also avoiding the painful java 8 to 9+ transition happening again
I truly do wonder to what extent will existing languages improve and to what extent will they be overtaken by new languages, unsaddled by backwards compat
yes
not sure why you think python needs to break backwards compatibility at this point
since there really is a lot being deprecated in every new release
ask me about being stuck in py 2.7
to this point
eh?
lol the depreciation rate is very high with python
that's what i was saying, no?
yeah, not really sure how to remedy it. You can't really rewrite the whole language to be expression based by now, and going half way would probably leave us in a scala like situation, just well, not as nice
yes i was agreeing with you
well, i think much of the situation could be remedied if we allowed true lambdas with a nice syntax
if that syntax needs braces to work, so be it :p
This. I've had people loose their shit at the very mention of braced codeblocks, but anonymous in-place callbacks are helluh useful for any asynchronous program. In Python, there is no good way to replicate
setTimeout(() => {
# multi-lined anon function goes here
}, 100) # setTimeout used as an example
I realize that adding support for braced blocks goes entirely against Python's indentation-based architecture, but there is no way you can't have both
Well, it doesn't need to be anonymous - just that defining it in other ways is akward
callbacks in networking or GUI programming are usually only needed a single time, so no point in naming them
def someMethodOnAClass(self):
variableIWantScopedInMyCallback = 1234
def someCallback():
return variableIWantScopedInMyCallback * 2
setTimeout(someCallback, 1000)
or
def someMethodOnAClass(self):
variableIWantScopedInMyCallback = 1234
@setTimeoutDecorator1000)
def someCallback():
return variableIWantScopedInMyCallback * 2
The javascript approach is simply easier to read, in my and a lot of other people's opinion
def someMethodOnAClass(self):
variableIWantScopedInMyCallback = 1234
setTimeout(() => {variableIWantScopedInMyCallback * 2})
In what way?
Oh, you mean the camel case?
nvm PEP8, you could call your anonymous function _()
XD I'm working on a project that enables pure-python DOM manipulation. To make things a little easier on JS developers who want to use it, the API is built with camelcase. Its my auto at this point
but using a def to define a one-off function simply is unnecessary boilerplate
And using lambda instead of an operator is just kinda silly
well, each programming community has its rules and guidelines, many Python programmers won't appreciate a library that uses camelCase
I'm using camelCase in TypeScript because that's what TypeScript uses and snake_case in Python because that's what Python uses
doesn't really matter, just a convention to have consistent naming across projects
"many Python programmers" aren't the only demographic I have to consider
there are enough python libraries that use camelCase, most of them wrapping around stuff written in other languages
yeah (also logging), it seems a bit out of place to the eye to be honest
Additionally, I'm going for as close a replication of the important JS API as possible. This lets Python developers directly translate JS tutorials they see online without having to do any translation and also makes life easier for JS developers
๐ ๐ ๐
You've worked with me on this many times, Fix XD
My current project has like 12 super long functions defined that I only use once
Would be cool if this stuff was added
Fat arrow or whatever
Its a graphics framework that launches an HTML renderer (cefPython) and creates a virtual clone of the DOM in the python runtime. Using custom descriptors on the elements in that proxy dom - prosto chango, pure-python web graphics
So no HTML/CSS/JS, it's just python?
If it's not super slow people are gonna love this
neat ๐
No, there's HTML. You write your HTML in numerous documents though, and a custom importer stitches them all together into a singular HTML composite. I know this might be a bit controversial but any web developer will tell you that HTML can get out of hand quickly. A modular HTML system is my choice as the developer and I stand by it. Beyond that though, HTML and CSS is onboarded by a custom importer. You can implement your own JS but its heavily discouraged. Modifying the DOM in javascript would result in de-synchonization between the two runtimes
Agda did the chad move and uses ฮป literally instead of lambda
Also lol
well, in ascii there are still more unused characters ๐
hell yeah, ] shell prompt
=> cough precident cough
what I could imagine would be something like unnamed decorator calls
@setTimeout(100):
print('it is now 100 millis later')
o.O
With respect - this is dumb
A decorator without anything to decorate is... well I don't know what that is
i'm not convinced either ๐
A closure, I suppose?
yeah, that's not great syntax by any means
too bad $ has such a bad rep
Always great talking with y'all
the issue is simply that a block as a full expression doesn't really have nice syntax. braces are great, but you would probably use something that doesn't conflict with a set literal, like <> or (), and even then, you are left with the incredibly ambiguous case of where should indentation continue. It's creates some tough to make sense of syntax, you can look at nim to see how it looks, it has indented blocks as expression
Food thought
def some_method():
some_variable = 1
some_callback_registrar(lambda :
# use normal block indentation here
)
The braces are really just for aesthetics. The salient point is the definition of functions anonymously as expressions (I think thats the correct terminology). You can impose the same restrictions on indentation for the anon function as you would any other function. Its where you can place the definition that counts. In terms of the grammar you'd just need to keep track of the starting indentation and apply all the same rules except also demand that at no point in the anon can anything have less indentation that of the line its defined on plus one
That still has ambiguities, but it is pretty much exactly how one of the syntaxes works in nim.
Using braces might be useful as start-end flags for the parser, but aren't requisite
It is definitely an option, however. There is sadly the question of
fun(lambda:
a, b=3
)
```not being super clear
I guess all I mean to say is that the arguments against multiline and more attractive lambdas are dwindling while the use cases are piling up. Even from aa minimalist perspective it seems like a good idea
Yeah, I think if someone proposes a good enough grammar, it would probably get into the language
But I haven't seen one that would work well
Lemme get back to you, in a years time, when I get to work on my language
Sure
hopefully you do better than the previous person who tried to make an ambitious language implementation ๐
I have much higher hopes for skywalker's language than for Leigh
well, keep in mind that you might want to define lambdas as dict values, so indentation alone might be difficult
Its just for learning purposes. Explore some ideas, learn what makes a language tick. Its like the programmer's equivalent of a triathlon. Coming in first is great, but just completing it is an achievement. Plus, I'll be annoying you guys with questions about it ad nosium
You do probably need an end tag of sorts, since the expression grammar was not made with an indented block in mind (see my second element/unpacking ambiguity)
that's not a good idea ๐
Patma more or less gives you this, just in a slightly more verbose and more powerful form
Yeah, I guess you're right
And well, unlike JS, you don't build objects of various values nearly as much in most codebases
In part thanks to optional arguments
you mean keyword?
Pursuant to a previous discussion, I've done aa bit of refactoring. Thoughts?
I wrote a script that could do that
by inspecting stack frames
it didn't work in all cases
but it was fun
I would honestly like {a, b} = {'a': 1, 'b': 2}
okay, I guess one problem is that Python has __getitem__ and __getattr__, whereas in JS they're effectively the same thing
that's not the problem i see, for me the syntax is ambiguous
and also not foolproof - just think of keys that can't be names
how is it ambiguous?
then you can't destructure them
I don't really see that as a problem
you can't pass such a dict to a function taking a ** argument too
that would cause a runtime failure
TypeError: keywords must be strings
but {a,b} means something entirely different to me
it looks like you're trying to make a set of sorts
at some level, yes
but sets are unordered so that wouldn't make sense semantically
and since {} are used for dict literals too I think the analogy is reasonably clear
exactly my problem
what do you mean by this
f(**{1:2})
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: keywords must be strings
yes
that's exactly what I said
it causes a runtime failure
ordered iterable destructuring does the same thing
For the record some_function(**{'some-invalid-identifier': 1}) won't throw an error, but using a non-string will
Wrote a script that could do what?
destructure
like a, b = {'a': 1, 'b': 2} with them going in the right order
and raising an exception if there's a mismatch
{a, b, **rest} = some_big_and_complicated_dict would be kinda nice, no?
We already do it with kwargs
it would, but
I would like similar functionality for attributes
and we're kind of running out of tokens
XD I was gonna say that, but I was afraid being asked politely to leave
About the attributes
{a, b} = some_object seems fine to me tbh. Most people understand that objects are really just dictionaries+ under the hood
If the dict de structuring was implemented you could do {a, b} = vars(some_object)
Dicts should just have a + operator that combines them
def __add__(self, other):
return dict(self).update(other)
def __iadd__(self, other):
self.update(other)
this = {**pretty, **stupid}
you can do pretty | stupid
Adding makes more sense if you ask me
not to me
It's what all the other data structures do
Or is just like
It works but you gotta think about it a bit
if you consider them as sets, kind of
Not as obvious
it makes perfect sense
kk
@quasi hound there were long discussions about this on the Python-Ideas mailing list, and likely a PEP covers why the syntax was chosen.
in general from what I can see, for stuff that isn't numbers, + is used when order matters and | when it doesn't
I like this rule of thumb
Order matters with dicts tho
a.update(b) โ b.update(a)
they compare equal
tbh I think mandating that dicts maintain insertion order was a bad idea
okay I guess if it's restricted to iteration it's fine
I DON'T KNOW ๐ฅด
!e
a = {"a": 1}
b = {"a": 2}
print(a | b)
print(b | a)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
001 | {'a': 2}
002 | {'a': 1}
okay, they compare equal if there's no overlap
๐ฅด
I think there was reasoning on this in the PEP
!e
print({'a': 1} == {'a': 2}
@quasi hound :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | print({'a': 1} == {'a': 2}
003 | ^
004 | SyntaxError: unexpected EOF while parsing
Ok shut up
why do you say it's a set
or rather
in what sense is it a set
I thought that's how hash tables worked
like are we talking about the abstract data structure set, the mathematical set, or the Python set?
!e
print(isinstance({}.keys(), set))
@gleaming rover :white_check_mark: Your eval job has completed with return code 0.
False
!e
print(type({}.keys()))
@quasi hound :white_check_mark: Your eval job has completed with return code 0.
<class 'dict_keys'>
I guess you could say it's set-like?
it's more the other way round, the initial implementation of sets was basically a dict without values, iirc, while mathematical sets are the most basic structure
it's a C object
without a direct analogue
dict_keys is a set, it's an instance of collections.abc.Set, and has all the same sort of operators and methods frozenset has.
From here: https://docs.python.org/3/library/stdtypes.html#dict-views:
Keys views are set-like since their entries are unique and hashable. If all values are hashable, so that (key, value) pairs are unique and hashable, then the items view is also set-like. (Values views are not treated as set-like since the entries are generally not unique.) For set-like views, all of the operations defined for the abstract base class collections.abc.Set are available (for example, ==, <, or ^).
that's why I asked this
like are we talking about the abstract data structure set, the mathematical set, or the Python set?
Set is the first one
Yeah. It's not an instance of set since that's a specific implementation.
indeed
I don't know from a purity form of view, but from a practicality side this has been exceptionally useful in specific circumstances.
So I can't fault the decision having seen how useful insertion ordered dicts can be
hey pls check #career-advice
Idk, I don't find it terribly useful
But also don't see why it was a bad idea
I'm pretty neutral to it
If you've been programming a while and in other languages it's pretty ingrained not depend on dicts being ordered
yup
for me too
sometimes
why is the logging module not using snake_case?
Because it's a port of the Java log4j library and predates Python standardizing on snake case
Yeah, unittest is based on junit
At the point where CPython began to preserve insertion order as a side effect of an optimization, the CPython maintainers decided it was more feasible to tell maintainers of alternative Python implementations that they need to follow suit than to tell developers of Python libraries that they must not rely on the CPython dictionary ordering behavior.
I think they were probably right.
OrderedDict is still useful when you need efficient reordering
I guess it just makes it a bit more of a specific use-case kind of deal than it used to be, as in a lot of cases insertion order would be all that is needed
yeah I remember reading about that
I actually hate JUnit so much
pytest is so good
test parameterisation and fixtures are beautiful
iirc they actually had dicts explicitely in a random order at one point to educate people not to rely on order
i find it very useful to have dicts be insertion-ordered
and sets should be too
retrieving items from a set is so unnecessarily hard..
it would make sets so much more useful if you could just pop() the last inserted item
Well, depending on how much you care about memory efficiency, you could write a simple wrapper that abuses dicts
(or stores the insertion order in a list)
sure could, but i'd prefer to have more useful built-in sets ๐
Their design is very different, which is exactly why they didn't get the same optimization as dicts which allowed to preserve insertion order
So if all you need is insertion order and O(1) membership, a dict with None values would do
dict_keys for set-like operations
Actually that reminds me about something I've been wondering about. ```py
class Hashable:
unique: str
other: int
def __init__(self, unique, other):
self.unique = unique
self.other = other
def __hash__(self):
return hash(self.unique)
Can I use a set to store these objects, and then get them back so that I can get the in-memory `other` attribute?
Or would I need to use a dict that uses unique as the key?
it;s hashable, it can go in a dict. whatever else you want to do is up to you
afaik you'd need a dict that maps a key to itself if I understood what you want correctly
you can retrieve it from the set if you iterate over it
i've done it before, but it's ugly as heck
hm, i'll be honest, i dont know why you'd want to use a set for retrieving things.
sometimes you want any item from a set
tbh i forgot why i needed to do that in the first place, it's been a long time past
Well, the reason is that I just want to keep a collection of these objects. But then I want to be able to get back the object if I have a similar one.
I don't really need a mapping for it with key/values.
Won't that even have some level of overhead if I use a dictionary? It stores the hash, key and value right?
There will be some overhead, but the question is, will it be significant enough to justify weird set hacks?
I'm not sure if there are any set hacks to do that maintain the time complexity
maybe just put these things with the key yourself*, and the value is the object.
You can store that in a set, and you can get a quick membership check, but you can't retrieve it gracefully
to me, that seems like the simplest straight-line solution
The example provided just looks like a dict with extra steps, but I assume it's simplified for the sake of being an example
well no, i understand the ask i think. basically, bluenix wants objects that are actively getting hash collisions
and in this case, that's a desried/expected thing, and so the existing object should be given back
to me however, that feels counterintuitive, so if i was coding it up, i would have explicitly put these calculated "hashes" as keys myself, the objects as values, and written out the if conditions explicitly.
Umm no, not really.
I have a bunch of these objects, and a lot of those other fields. Sometimes I construct a new object with the same unique, and so in that case I want to be able to grab the old object.
Yeah, the issue is that I am imagining this as a sequence of just free floating objects. But I guess it's actually more- or less a mapping.
Yeah I'll just go ahead with that ๐
ah okay, yeah i think that's the simplest solution ๐
Hmm
Plus in the end there is a Timeout error so is there any way to fix that error
Hey, could anyone link me to a website/git that has a SHA256 code that uses pure mathematics without using a module?
what is "pure mathematics"?
not using a module to compute the algorithm
just if, else, while, and other built in functions
serious implementations are all in lower-level languages, not in python
for performance reasons it seems
performance is not an issue anymore lol
@verbal escarp
is there a code that u could link to me?
im in a hurry
Is there a good file format for storing 2d arrays that expand in length and width. Serialization might be the only option I can think of off the top of my head.
"expand"?
as in grow from 200x200 to 400x200 or 600x600 to 800x800
I think this is the wrong channel for your question. Maybe open a help channel?
I would but Iโm just spitballing here with no actual code
i'd try #algos-and-data-structs maybe, it's offtopic here
Forgot that channel existed thanks
Has anyone ever had an issue with string.__contains__ not working in a Linux environment, but no problems on Windows? Same versions of both py as well as all modules from pip
Edit: pip actually not relevant
what issues?
Sorry for late response. I asked in help but I think it was a little advanced. I have a function that takes a <5mb JSON array with nested arrays full of pictures - probably 20,000 images per response. The function that works without an issue simply uses a nested for loop and iterates over the array and appends the MediaURLs to a new array and returns that back to the calling function.
This was an almost identical function (i removed the others would need to dig through github), except it returns the total count of the array:
def count_media(data):
count = sum([len(value['Media']) for value in data['value'] if value.__contains__('Media')])
del data # Not sure if necessary here
gc.collect()
return count
Using that function structure to build both the array of urls and well as get the count had no problems on Windows.. either that or I had restricted the limit of the API request and there is a bad set of data in that specific pull (or missing Media key). Either way, the contains didn't seem to help it.
That can be simplified to just
def count_media(data):
return sum(len(value.get("Media", [])) for value in data["value"])
what's with the manual del and gcing
So the import script, if we replicate from the beginning of the vendors database, it downloads over 1,000,000 real estate listings and processes appx 17m jpeg files in total (request streamed into another s3 bucket). After it has ran about 20-30 times, if we dont del the data or run gc.collect() it will run OOM. One thing we weren't sure of was if the del was required for gc.collect() to clear the data in memory
del only gets rid of that reference to the object, if there are other references the object will stay alive
I am going to test this out.
Thank you for this - we have been looking into gc and how it works a bit. This helps.
Sanity check - this snippet that reverses a slice of a list will create the reversed slice fully and separately before putting it back in the list, right?
!e ```py
a = list(range(10))
print(a)
a[2:8] = a[7:1:-1]
print(a)
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
001 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
002 | [0, 1, 7, 6, 5, 4, 3, 2, 8, 9]
and thus would use more memory (O(N)) than a slice reverse could do if optimal (O(1))
Yes.
If you're in doubt you could look at the dissassembly
I forget how to do that 
!d dis.dis
!e like this
py import dis def f(a): a[2:8] = a[7:1:-1] print(dis.dis(f))
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
001 | 3 0 LOAD_FAST 0 (a)
002 | 2 LOAD_CONST 1 (7)
003 | 4 LOAD_CONST 2 (1)
004 | 6 LOAD_CONST 3 (-1)
005 | 8 BUILD_SLICE 3
006 | 10 BINARY_SUBSCR
007 | 12 LOAD_FAST 0 (a)
008 | 14 LOAD_CONST 4 (2)
009 | 16 LOAD_CONST 5 (8)
010 | 18 BUILD_SLICE 2
011 | 20 STORE_SUBSCR
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/hobaxawifi.txt?noredirect
not totally sure how to read it
but I see BUILD_SLICE in there
Yeah you can see it happens twice
Maybe it would be more obvious if you compared it against a version that assigns the slice to an intermediary variable before inserting it. It shouldn't be much different.
!e py import dis def f(a, b): a[2:8] = b print(dis.dis(f))
@unkempt rock :white_check_mark: Your eval job has completed with return code 0.
001 | 3 0 LOAD_FAST 1 (b)
002 | 2 LOAD_FAST 0 (a)
003 | 4 LOAD_CONST 1 (2)
004 | 6 LOAD_CONST 2 (8)
005 | 8 BUILD_SLICE 2
006 | 10 STORE_SUBSCR
007 | 12 LOAD_CONST 0 (None)
008 | 14 RETURN_VALUE
009 | None

I mean like this
!e ```py
import dis
def f(a):
b = a[7:1:-1]
print(b)
a[2:8] = b
print(dis.dis(f))
@charred wagon :white_check_mark: Your eval job has completed with return code 0.
001 | 3 0 LOAD_FAST 0 (a)
002 | 2 LOAD_CONST 1 (7)
003 | 4 LOAD_CONST 2 (1)
004 | 6 LOAD_CONST 3 (-1)
005 | 8 BUILD_SLICE 3
006 | 10 BINARY_SUBSCR
007 | 12 STORE_FAST 1 (b)
008 |
009 | 4 14 LOAD_GLOBAL 0 (print)
010 | 16 LOAD_FAST 1 (b)
011 | 18 CALL_FUNCTION 1
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/lopeliqiga.txt?noredirect
the print demonstrates that it is indeed a full object of its own
And apart from the print call and loading the slice from the b variable, the disassembly is the same.
ah, I see
What is the difference between front and back end coding
Front end .. is about the design of what is shown on the screen , colors , fonts ..etc
Back end is about store the data of users , passwords , etc ๐
Ok thnx
It's like when you click on subscribe button it becomes read that is the front end work and the process is made from the back end people.................... ........ this is from ehat is understood
Is it right?
More or less. Usually in web development, the "front end" is what the user interacts with in the web browser, and the "back end" is a server that handles requests sent from the frontend
Ok thnx it was helpful
What are you guys' thoughts on beartype?
I'm reading through the docs and, beyond being hilarious in their own right, indicate they are aiming for production-grade runtime type validation in Winter 2022
a lot of types cannot be checked at runtime, for example you cannot verify that a list[bool] is actually a list[bool]
but it seems useful when you are aware of it's limitations
Can you expend on this?
Why can't you?
it would incur massive runtime costs, imagine if it was 100000 long
So, you can, you just shouldn't
yeah, but that's why you can't do it realistically
all_bools: list[list[bool]] = []
def add_to_bools(arg: list[bool]):
all_bools.append(arg)
my_list: list[int] = [True, False]
add_to_bools(my_list)
my_list.append(5) # oh no
also, functions, coroutines, dictionary and list subclasses, generators, ...
I'll be doing more reading on it, but my understanding is that such challenges are exactly what they're working on
I mean, if they can solve the halting problem, good on them
you could keep tags on the types to remember the content they expect, so a fuction would only error when called etc
which is not bad all things considered
but IDK how you would keep those tags on python objects
*"Beartype 1.0.0 brings us perfect compliance constant-time compliance with all annotation standards. That's good. But is that it?
It is not."*
They're aiming for 1.0 in December 2022, though I'd imagine mid 2023 is more realistic
it's an interesting project for sure
Of course, I don't expect some revolutionary mathematical proof or whatnot, but "compliance with all annotation standards" would sit right with me for sure! ๐
it they can keep a runtime tag on an arbitrary object to track all protocols it has ever been assigned in constant time, I would be very impressed
The reason I'm asking is, well, I imagine I'll be finish up this project in a year or so, and it'd be nice to equip it with beartyping when that becomes possible
Its more than enough already, I suppose, for a limited scope. It can do built-in types, most nested generics, callables. Its the curious cases they're working on now I think
The real headscratcher I've got going on right now is that I don't like the error messages they put out. I'd like to rewrite them, but its not as simple as just catching the error and replacing it with my own because information about what caused the error isn't really carried along with the error
I could, I suppose, copy-and-paste the library and just rewrite the exceptions
I guess the most pythonic approach would be subclassing their decorator, studying the nuts-and-bolts of how it works, and just overriding the bits relevant to the writing of the error
I see, this isn't really a type safety tool, more of a error faster tool
For generic types it makes much more sense to let the type protect its own type invariant
Rather than try to verify downstream
does anyone know why this behaviour is in python? for me it doesn't seem like there'd be any benefits for this redundancy; since a += b is equivalent to a = a.__iadd__(b), why does __iadd__ modify the list in-place, and return it again for assignment? it seems like only doing the return would suffice for augmented assignment syntax ```py
a = [0]
a.iadd([1])
[0, 1]
a
[0, 1]return AND in-place?? weird
it's an optimisation of sorts
__iadd__ is made special like that exactly to allow in place modification
for example
some_numpy_array += 5``` should not copy the array
sorry, i'm not really understanding this example... isn't a simple return already enough? my question is, why modify it in-place before, then return?
it will have the same result, but consider a 10000 long list
memory allocation
you would have to copy the list, add one element to it, then return the new list, then remove the old list from memory
I think it's more than the semantics of __iadd__ is the same even if it's being used for a data type that doesn't get modified in place.
BUT INSTEAD, YOU CAN JUST MODIFY IT IN-PLACE, THEN RETURN IT
OMG
PYTHON IS AMAZING
WOWOWOWOWOWOWOOW
.bm 874008100510761031 for further reference :DDDD
oh? lancebot should work in this channel?
lol time to open issue
I dunno, maybe it is intended. Anyway, consider int.__iadd__ You can't change the int in-place (unless it has a special implementation in C), so a write to the symbol table is necessary.
!e
a = 5
def foo():
a += 1
print(a)
foo()
print(a)
@boreal umbra :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 7, in <module>
003 | File "<string>", line 4, in foo
004 | UnboundLocalError: local variable 'a' referenced before assignment
i'm pretty sure int objects don't have __iadd__, but instead fall back to __add__ and __radd__ during augmented assignment
interesting
okay, so summary: mutable objects that can perform in-place changes change in-place first before returning the changed object in __iadd__ so that they don't have to recreate a new object with the increment (which would be in the case of only return, no in-place change), because that would be less efficient from the extra memory allocation python has to do @flat gazelle @radiant fulcrum @boreal umbra
am i right?
pretty much
yay! thanks a lot y'all, this cleared it up a bunch!!
what seemed like redundant at first actually had PythonBlackMagicโข๏ธ underneath, this is so cool
this behavior does get a little unintuitive in some cases tho ```py
x = ([],)
x[0] += [1,2,3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
print(x)
([1, 2, 3],)
this was exactly what started my journey down the rabbit hole in the first place
understanding this weirdness
yea its easy to see why it does that by looking at dis output and knowing how INPLACE_ADD works
uh wat
you're telling me you can x pow= 3, 5 or some crap like that? ๐
why is the modulo param even in there- ternary augmented assignment doesn't exist
or does it
same with this here
Note that ternary pow() will not try calling rpow() (the coercion rules would become too complicated).
so then... why the heck ismodulothere
I assume ipow is used by a **= b
of course, and __rpow__ as well as the reflection for a ** b, but the parameter modulo is only used with the pow built-in function
and to my knowledge, you can't really augmented assign a function call lol
hmm, yeah, there doesn't seem to be much of a reason for that
i guess it's to just be clean and uniform? even though that optional param will never be defined in these two dunders
The argument probably exists because the pow builtin and direct uses will use that method
this is super weird lol
but why would you call __rpow__ manually
but not for __rpow__ and __ipow__
pow(1, 2, 3) would be int.__pow__(1, 2, 3), because we know that __rpow__ won't be used in this case (it's only used for ** syntax)
so __rpow__ and __ipow__'s modulo parameter is useless
ofc, like @flat gazelle said, you could call it manually
but no one would do that
debug purposes, perhaps?
does python have support for something like async lambda?
more or less no
why? is it just that nobody has ever attempted to add it or was it proposed and denied for some reason?
I believe there wasn't much reason. For almost all the cases, you can just return the unawaited coroutines
I mean, that's kind of the same as saying that you can just pass in the function object
this means that the async function still has to be defined as a function which is a bit unpractical for certain use-cases, this is pretty much the same problem that lambda solves with sync functions
yeah, it would be neat, but I am not sure it's important enough to really be worthwhile, I don't mind the
async def a():
async def b():
pass
return b()
```that much
I would find it quite useful with unit-tests, I often find myself having to either write an async mock and define what it's call will return, or define a full async function and pass that in so that a function can await given coroutines even if they only return a static value
I don't suppose that there's an easy way to convert regular sync functions to coroutines
!d asyncio.coroutine
@asyncio.coroutine```
Decorator to mark generator-based coroutines.
This decorator enables legacy generator-based coroutines to be compatible with async/await code:
```py
@asyncio.coroutine
def old_style_coroutine():
yield from asyncio.sleep(1)
async def main():
await old_style_coroutine()
```...
it's not really a generator based function though
not sure when they are getting depracated though
that's good, otherwise this wouldn't work
yield from is await
yeah, but I meant simple return
then just return
like ```py
make_coro(lambda x, y: True)
!e
from asyncio import coroutine, run
async def amain():
print(await coroutine(lambda x, y: True)(1, 23))
run(amain())
@flat gazelle :white_check_mark: Your eval job has completed with return code 0.
001 | <string>:3: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
002 | True
but well, yeah, the decorator is going away soon
you can use types.coroutine
ah, didn't know about that one, that's useful
if all you want are constant coroutines, you could also just do
def make_coro(fun):
async def coro(*args, **kwargs):
return fun(*args, **kwargs)
return coro
!e ```py
from types import coroutine
coro = coroutine(lambda x: True)
await coro(2)
@deep bramble :x: Your eval job has completed with return code 1.
001 | File "<string>", line 3
002 | SyntaxError: 'await' outside function
the coroutine from types is a bit more limited in its use than asyncio's so I'm not sure if you can use it on a lambda like that. Not sure what it does with normal functions
yeah, that's pretty much what I wanted, is something like this in the standard library though? ideally I'd stick to already implemented functions then making a decorator like this, it's not a huge issue, but if there is a function like that already, it would probably be better to just use that
other than the depracated asyncio decorator, afaik no. py In [21]: from types import coroutine ...: coro = coroutine(lambda x: (yield) or True) ...: asyncio.run(coro(2)) ...: ...: Out[21]: Truethis does work,but it isn't all that great
hm, well thanks I suppose I'll go with the decorator then, but yeah, this is precisely why async lambda would be great
I use arch
the core job of async is waiting, and no matter how you implement things, you will wait just as long
Thoughts on this talk? https://www.youtube.com/watch?v=XU9_3AlCy84
Christopher Neugebauer
https://2020.pycon.org.au/program/VVNEZR
When you type โimport thisโ into a Python interpreter, you get PEP-20, 20* aphorisms that describe what โGoodโ Python code looks like. Most of these are prescriptive, and have been used to settle countless arguments about how Python should grow, or how new ideas should be implemen...
Folks,
What's the best library to randomize color of a pixel artwork? Or even modify it?
mmm probably numpy
at the end of the day a picture is just a big array of numbers
numpy's ability to very efficiently apply operations to the array makes that easier and quicker
Ok, saw this talk, seemed just fine to me. I will admit nothing in there seemed like groundbreaking revelation or anything, maybe i missed something
yeah I think it somewhat sums up some disagreements on the mailing lists when people were trying to back up their position using the Zen
can't really find the place
I didn't even think anyone was claiming that the zen would give you the end-all be-all answers to how to code, so to me, all i watched was an opinion fleshed out which i didn't think needed fleshing out.
whats computer science guys?
The study of computation. How problems can be formally solved via algorithms.
I know this is super cursed, but is there a way to make a conditional check about the type checker? Like
if using mypy:
...
elif using pyright:
...
elif using pyre:
...
else:
...
so that mypy only detects its block of code as non-dead, pyright its own and so on.
the first thing that comes to mind is that each type checker presumably has different ignore codes, so...
not necessarily true + not scalable though
I guess the real solution is to standardize typing, but, well
@gleaming rover maybe you can see #dev-contrib where we're having an issue? <#dev-contrib message>
basically, we want to make a thing called Arg where you can only invoke Arg[A, B] where B has to conform to SomeProtocol[A] (A should match the first argument), at runtime Arg[A, B] should evaluate to B but to the type checker it should be equivalent to A.
maybe theres a way to pipe the code through something that can tell if/which type checker is being used
okay, I read the chat and I kind of get it
feels like just inconsistencies in 3rd party type checkers ๐
so like...
def func[A, B <: ConverterT[B], ConverterT[_]](a: A): B = ???
that's what I'm thinking
not sure if my mental model is right I just woke up
but no ideas, sorry ๐ tbh I don't even use anything but PyCharm's checker
@gleaming rover I made a hack that works with Pyright https://gist.github.com/decorator-factory/718a6b6bf514c496baf385f0c0cfcdaa, but mypy doesn't like it
yeah I saw
I also ran the mypy snippet
like
The background of that is that we wanted to make discord.py play nice with type hints. Right now you convert argument like this ```py
class IntConverter(Converter):
async def convert(self, ctx: Context, argument: str) -> int:
return int(argument)
async def my_command(ctx: Context, number: IntConverter):
...
and at runtime, `number` will be `int`, which screws with all type checkers. So we wanted to make something that would allow ```py
async def my_command(ctx: Context, number: Annotated[int, IntConverter]):
...
```, so that the type checker is happy, and the library works. But using `Annotated` requires monkeypatching discord.py, and it doesn't ensure that `int` is what `IntConverter` produces.
okay I haven't really used it but my guess is this is because the raw command is a string
but you want to turn it into a more appropriate type
just like parsing URL parameters
yeah yeah, like FastAPI
so in the case of a command wiht one argument
I'm not entirely sure how it works, but the central problem we're solving is that discord.py uses annotations in a way that is not compatible with type checkers
hm.
so this is fundamentally a discord.py problem
that we're trying to work around
yep
is there a way
to mark one type as a subtype of another
?
tbh I don't know how the tools work
nobody knows how they work
like in the abstract sense it's not a super hard problem but I have no idea how to implement it
the gist of it is that you want to take an argument Wrapped[T] and have it be treated as a subtype of T
in the function body
right?
so you enforce two constraints: that it is an instance of Wrapped (the converter) and it can be used as T (the output value)
that feels like the simplest solution to me without going into rather complex stuff
why not just a TYPE_CHECKING block where you set the parameter to the actual type?
and fwiw this only is a problem for custom converters
You mean, ```py
if TYPE_CHECKING:
DateType = int
else:
DateType = MyDateConverter
perhaps you should comment that on https://github.com/python-discord/bot/issues/1730
nah i'm not gonna get into a discussion about monkeypatching the lib
that should be a last resort
What's the proper way to add documentation to attributes? Methods have docstrings, but attributes don't
And I don't want to create a no-op property for every attribute
@grave jolt sphinx recognizes a string literal after an attribute or top-level definition as a docstring
a = 12345
"""This is the 'a' definition."""
๐ค interesting
In my case, I just want to document private attributes in code
So I wanted to know which style is the least cursed to other developeres
If it's for private stuff why not simply a comment?
Kind of confused
Like I think salt did, I assumed the reason you were asking was because it was some kind of public doc
Yeah I guess I can just put an inline comment
Work on typpete is coming along nicely:
https://github.com/adsharma/Typpete
https://github.com/adsharma/py2many/issues/96
https://github.com/caterinaurban/Typpete/issues/59
Would love to get more feedback on what's not working well. Should have it on pypi once the naming/forking issue is resolved.
I think it would be useful to utilise https://github.com/ilevkivskyi/typing_inspect , or similar to offload some of the type inference/analysis work.
I've made some usability improvements in the fork at: https://github.com/adsharma/Typpete A few questions: Are these improvements interesting? If not and if you'd prefer that I main...
They do, like Salt Rock Lamp showed above is the official way. I read the PEP a while back.
oops wrong channel sorry
... pass
...
>>> class B(A):
... pass
...
guys can we pass info from B to A
program execution most come to B before going to A. we will pick that point and add some info to it, before the program execution goes to A.
can we add some info in A from B
@olive marsh you would be able to call methods defined in A on an instance of B, yes
No I want to pass info from B to A. i know i can call functions of A from B
call i make this other way round
i just want to pass some info
What do you mean by "pass info from B to A"?
like my class A has everything inside it. you can initialize that class only but user can subclass the A and add some info to it. according to this the behaviour of A gets changed
sorry, i don't know how to ask. I am confused, dealing with an internal framework of the company. I will ask someone from the company.
Btw,edited my question
If this is the ask, to me it sounds like the Y of an XY problem. Perhaps there's a better way to organize or refactor this code.
Now, having said that, technically B could just make an instance of A class and probably achieve whatever you're thinking of. But I can't help but feel that in that case do B and A really have a subclass relation?
Hey everyone i am encountering very weird issue
I have MacBook m1 and i am not able to run psycopg2 as i get import error
These are the sc. I am using fast API and it was working fine , until i added import psycopg2
def get_piece_moves_at(self, y: int, x: int) -> List[Tuple[int, int]]:
board = self.board
piece = board[y][x]
direction = self.get_piece_direction_by_color(piece)
moves = []
new_y = y + direction
try:
if board[new_y][x] is None:
moves.append((new_y, x))
except IndexError:
return []
for x_ in (1, -1):
new_x = x + x_
try:
if board[new_y][new_x].color != piece.color:
moves.append((new_y, new_x))
except IndexError:
continue
except AttributeError:
continue
``` is this bad 
I'm pointing at the try except
it's not the worst thing in the world, but why AttributeError? are you checking for None? also this code looks a lot like (exactly like?) some code i worked with in a help session a few weeks ago.
is this from a leetcode type of website or some popular online course?
๐ why doesn't divmod fall back to __floordiv__ and __mod__... why do we need to explicitly create __divmod__
if am not wrong, immutable's are addressed by value and mutables are addressed by reference?
no, both are handled the exact same way
https://www.youtube.com/watch?v=_AEJHKGk9ns this talk is the way to make sense of how python objects actually work
they aren't defined
I mean
how does it state that it's an immutable
how else does it know it cannot be changed?
oh
so its like no __setitem__ for tuples/strings?
yup
Would you guys mind taking a look?
I've made my thoughts on runtime checking fairly plain in the past (I'm in favor). This little setup of code is to validate a dictionary of configuration-settings passed in at startup by the user. It uses beartyping in place of instance checks because beartyping can handle generic types
I think this setup will give me a fair bit of flexibility in validating many different types with different requirements
I just need to write in the errors
If this pans out, I might make it possible to dynamically add new conditions (like the min-length checker). Could be interesting to see
@static bluff side note: you might enjoy clojure or clojurescript
rich hickey feels the same way as you do about static types
rather, you might find his thoughts interesting
praise
Thanks! ๐
Is it possible to make a type checker think X is a subclass of Y without actually making X subclass Y?
Does typing have any mechanism for that?
That depends on the type checker
Hold on
Let me rephrase then
Is there a consistent, standardised way to do the above?
Specifically, you're talking subclass and not instance of
not in a consistent standard way, i don't think so. unless mypy is somehow able to identify ABC registration
you might need a protocol
I don't think so.
If you're talking about the discord.py converter question, I already gave up in my usual style ๐
No it's not about that.
does mypy not recognize explicit registration? that's disappointing
class Thing(Generic[A, B]):
...
class ThingLike(Protocol[A, B]):
...
# no
def foo(thing: Thing[A, B]):
...
# yes
def foo(thing: ThingLike[A, B]):
...
Maybe you want a protocol?
The context is that arrow.Arrow implements the datetime.datetime interface but doesn't actually subclass it. This causes type checkers to complain if I pass the former where the latter is expected. I can't really modify either one unless I monkeypatch.
yeah
a protocol is basically an interface that the static type checker implicitly checks for satisfaction
as opposed to someone having to explicitly declare that the type implements the interface
protocols do have some unobvious behaviour, like how a property doesn't satisfy an attribute and vice versa
How would I use a protocol?
Third party library has a function that expects datetime.datetime
I use arrow.get() to receive an arrow.Arrow
ah then you're boned
yeah
the argument would be, this third party library asked for exactly a datetime.datetime, they annotated it as such
so you can't really assume it's okay to pass anything else
yep, and they could do something like assert isinstance(foo, datetime.datetime), or later use in a union, which could break stuff
write wrappers that take arrow.Arrow, convert to a datetime.datetime, and call the function ๐คทโโ๏ธ
yes this is in fact the other problem I face. it's unfortunate
but yeah this is generally the kind of reason why standard libraries are nice
For the isinstance problem I thought of monkeypatching arrow to return an Arrow subclass that has a metaclass with isinstance and issubclass hooks
yeah
Well arrow has arrow.Arrow.datetime but I just wanted it to be more transparent
I don't wanna use .datetime every time :(
just alias the type as something locally then?
a few extra characters is definitely not worth any sentence with the words monkeypatching, subclassing, metaclass, isinstance, and issubclass all in it ๐
it'd be nice if we had a protocol_from thing
ProtocolFrom[datetime.datetime] would mean "treat this as a Protocol but with all the annotations from datetime.datetime"
just implement traits and create a Datetimeable trait ๐คท duh
protocol_from is a nice workaround, but people should probably be programming more against interfaces to begin with
well, programming to interfaces everywhere can lead to more complicated code, which wouldn't really look like Python
like, imagine if Sir Lancebot applied dependency inversion
out of curiosity, why do you think that?
do you think a function is simpler if it says that it accepts List[int] instead of Sequence[int] ?
Sir Lancebot? Who is this man, and is he married? Cause I'm wide open
the thing is that in python you're really always programming against interfaces (or almost always), anyway.
Maybe. With isinstance checks it's frustrating because it goes against duck typing. Here I am with a type that would work totally fine as a replacement if not for that check. It's not even really the libraries' fault because they don't have an easy way to say "I need a type that behaves like datetime.datetime but it doesn't specifically have to be that one". Even with protocols it doesn't fully solve the problem since that cannot encode behaviour.
So cornering the type system and preventing it from doing something properly that you're really already doing seems silly
๐ค
@charred wagon what do you mean by "protocols cannot fully solve the problem because they cannot encode behavior" ?
not exactly. what he's saying is true in the sense that protocols only check for syntax; they check for functions with certain names and certain signatures/annotations.
That said the type system just can't check behavior for you
If a function has a side effect, a protocol cannot encode that information. So the only way to be sure you'll get a type that performs that side effect is to annotate with that exact type.
if a function has a side effect, the python type system generally cannot encode that information?
or maybe I should say, maybe it could in theory, but it just doesn't
people don't write python that way
Well, in case of datetime, you'll need to create your own DatetimeLike protocol or such and specify explicitly the interface of what you're expecting.
So if you accept datetime:
"I accept datetime.datetime"
And if you accept "datetime or the like"
"I accept any object that has these properties: ..., for example a datetime.datetime"
Yeah, I know. I'm just justifying the situation with using isinstance
that's what Haskell is for ๐
I'm just saying the limitations of the type system in terms of not being able to encode all the behavior don't have anything to do with your immediate problem
There's the returns library and the such...
I wasn't trying to say that was the case.
well, you said "protocols don't fully solve the problem", but that problem is completely orthogonal to what protocols are about ๐คทโโ๏ธ
speaking of behaviour, even in Haskell you pinky promise that you obey certain contracts when you implement an interface (create instance of typeclass)
Sure, of course
If your type system can verify all the behavior then making your types work is the same as writing a working program
you've definitely sold me on this btw
hey man, this is the internet, you're not allowed to be persuaded about anything...

i think given the state of python, ProtocolFrom could be a good idea. maybe i'll post on typing-sig or python-ideas
i'm sure it's bad for some reason or other
Yeah, it would definitely help given the practical realities of things.
Oh, I just read to this point. Yeah I agree that it would be a good idea if this is all you needed to do
I guess the biggest issue would be that type checker maintainers would need to implement quite a lot of logic to support that
like, Pyright is already nearing the lines of code of the Agda compiler
but, to mention again an example I've probably mentioned before, in Kotlin, List and MutableList are interfaces. Nobody really uses the "concrete class" in typical programming. And it's fine.
the issue with Python is perhaps that some built-in things (iterables, iterators, callables, etc.) are extensively used in a duck-typed way, but other things (like datetime.datetime) are used in a nominal way, or something like that
can you explain what you mean here by nominal?
interfaces are also nominal typing
okay, that's not so much nominal vs structural, but just the fact that they are using interfaces in one case, and concrete classes in the other
I don't understand, sorry. I'm saying that it can use a protocol and that solves the problem of subverting duck typing, it still leaves it with the problem of not being able to guarantee the behaviour. So "the problem" is both being able to program to an interface and being able to expect certain behaviour. This isn't about my issue but rather about the issue libraries face.
if someone annotates with Iterable[int] or something, life is simple because that's not a particular class
the issue is more with open vs closed types, though most python types are at least somewhat open
but well, a Protocol or an abc is far easier to implement than a subclass
@charred wagon but that has nothing to do with protocols, the fact that the entire python type system, generally, cannot guarantee behavior.
(well, any type system really)
even if you annotate exactly datetime.datetime, someone can inherit from datetime.datetime, and have a derived class whose behavior doesn't have the invariants expected by the library
Er... I am not saying that it has something to with protocols. I'm saying: we have problem X and Y. Protocols can solve X, but that's 50% of the problem and we're left with Y.
Okay, even then though, Y is just literally an intrinsic problem of all type systems? Not something that libraries need to "worry" about per se... it would just be user error if someone implemented an interface (including behavior) incorrectly ๐คทโโ๏ธ
Protocols don't require you to explicitly subclass them/get registered
yes
you just implement it, and the static type checker implicitly recognizes that it fulfills the protocol
well, sometimes you don't control the class
@charred wagon
An interface usually contains the function shapes and some invariants that the implementors promise to obey. Like how Sequences promise that their __len__ returns a number x so that indices [0; x) are valid. Perhaps I'm misunderstanding what you mean?
but then you can register, is the counter-argument
in python specifically, protocols make a kind of sense because the "real language", which has no static typing of course, is duck-typed
so, it makes a kind of sense, you make the static typing world kind of follow what's already happening in the dynamically typed language underneath
In a broader context, yeah, I don't think that structural sub-typing, i.e. python protocols, are a great idea
they're featured in Go.
and offhand I don't know any other mainstream statically typed language that uses them.
OCaml and PureScript, but I suppose that's not very mainstream
also TypeScript, but it's not "real" static typing
i think they probably seemed like an upgrade because in the past, the main thing we've had is inheritance. and inheritance is intrusive. So it can be a big headache if you don't control a class but want to make it satisfy some interface.
clojure's spec is pretty much structural, but it's a question of whether that's a real type system
That said, a bunch of languages now solve that problem in a different way
which is they make it explicit, but they allow either the person controlling the type, or the person controlling the interface, to explicitly declare the relation
this is what Haskell and Rust and Swift and I'm sure many more languages do
For example, utcnow() returns a naive datetime in UTC. Naivety is when tzinfo=None and for it to be in UTC, well, that just has to be documented cause time zone is ambiguous by just looking at a timestamp without any tzinfo.
That possibly could be represented as types, but the current interface is designed to just return a datetime, which is the same type as aware times.
yeah, this stuff though was designed long before static type checkers though so people didn't really design things with better static enforceability in mind
definitely, naive and aware datetimes should be separate types
For what it's worth I think naive datetimes are just a bad idea in general
i'd say it's a "contract system", not a "type system"
that seems like an over-aggressive stance for a library to take, but it could probably work in some cases
definitely in some languages/domains that's just not practical
i wonder if it would be a lot of logic? seems like it shouldn't be that complicated, the annotation either can be looked up or it can't, and if it can't you have an option to treat it as object or Any or an error
"shouldn't be that hard" is famous last words though
The good news is that "shouldn't be that hard" mapped to a known problem, so when that problem is solved, we'll have a solution!
The bad news is that it mapped to the NP complete class of problems ๐ฆ
Yeah, I didn't consider that isinstance would also pass for subclasses, so I incorrectly assessed why isinstance could be used. I guess if there was an isinstance that rejected subclasses, that would be stricter. Anyway, yeah it's still susceptible to other hackery like monkeypatching.
e.g. what if you have this ProtocolFrom[Foo] in a union? how do you do type narrowing on it? as far as I know type checkers don't support hasattr-based narrowing yet. What if you have ProtocolFrom[Union[Foo, Bar]]?
it's when the duck gets hurt and the monkey patches it
If isinstance rejected subclasses though then breaking LSP would be too easy
maybe just ban unions in ProtocolFrom? seems like a reasonable restriction
the bottom line is... this stuff is hard ๐
isn't that literally the point of isinstance
you can use type(x) is Foo otherwise
yeah
in the first part, I meant Union[ProtocolFrom[Foo], ProtocolFrom[Bar], Baz]
well that's the big reason why isinstance is recommended over type is
is that different from Union[ProtocolA, ProtocolB, ProtocolC]?
at any rate. I think in the future what can help is the standard library defining more interfaces
and encouraging people to use them
not having a "file-like" interface is really annoying, if only for docs searching purposes
I mean even now they coudl define ABC's/protocols for datetime stuff, and make their own datetimes inherit/conform to thos interfaces
and libraries could actually change their tyep annotations to the interfaces
this is actually a non-breaking change since it's broadening
Indeed. Is there anything that does enforce behavioural subtyping? Seems like a really difficult problem.
when you say "behavior subtyping" what exactly do you mean? Like, promising that subtypes of an Integer interfaces, have the invariant that x + y == y + x ?
Protocols can be made runtime-checkable (i.e. they check for method names, which can have issues). I guess you can make ProtocolFrom[...] runtime checkable, but that moves the complexity into typing.
maybe it's not that bad though
btw, while I like python's type annotations, and I see the benefit of gradual/optional typing in some cases, conversations like this and coding experiences like this, have convinced me that I'd basically just prefer a statically typed language.
Yes, the gradual typing does give you some options you don't have in a statically typed language. But there's actually a pretty big complexity tax to reconciling two type systems in your language now.
I've felt this way for a while, ever since I've tried to use type annotations in non-trivial ways.
I suppose runtime-checking protocols in general suffers from this issue: ```py
class Point2D(Protocol):
x: int
y: int
class Point3D(Protocol):
x: int
y: int
z: int
that's a very good example
let's continue:
def norm(p: Point2D) -> float:
return math.sqrt(p.x**2 + p.y**2)
very very misleading
recently pyright disabled narrowing on non-final TypedDicts for a similar reason
i.e. when you have ```py
class Foo(TypedDict):
x: int
class Bar(TypedDict):
y: str
def thing(foo: Union[Foo, Bar]):
if "x" in foo:
# it's a Foo
else:
# it's a Bar
class Baz(Bar):
x: str # oops
I'm not very well versed in it. I believe it's a more sensible form of LSP where it doesn't enforce strictly identical behaviour but rather that it at least perform the same behaviour. Something like that.
LSP doesn't enforce identical behavior
if the subtype behaved identically then obviously there would be no point in it existing
Right, and that's the problem with LSP
that there's no enforcement of what's "substitutable" ?
I think it's not clearly defined
It's not that it's not clearly defined
it's just that it completely depends on your code
it completely comes back to the contract of your interface
it's the job of the parent class to define what invariants it has
and a subclass is substitutable if those invariants are respected
I think that's a reasonable definition
in many cases realistically there aren't even iron clad invariants
there's just... desired behavior
yeah, well, invariant is a strong word
I've managed to find were I originally read this from. Wikipedia of all places https://en.wikipedia.org/wiki/Behavioral_subtyping#"Substitutability"
"x" in foo and isinstance(foo["x"], int) might still be unambiguous though
i think narrowing on typeddicts is pretty niche anyway and you probably shouldn't be doing it
Amusingly it seems like Liskov's original definition was that the behavior be "identical" which is silly (as wikipedia notes), and Liskov talks a bit about that.
class Foo(TypedDict):
x: int
class Bar(TypedDict):
y: str
class Baz(Bar):
x: Union[int, list]
well yeah in that case there's nothing to narrow
i don't think any narrowing is possible in that case, right?
๐ค yeah I guess, it's just that Foo and Bar could have different semantics, so x could mean different things in Foo and Bar, so the matching would've been unintentional (like in Point2D/Point3D)
how do go and ocaml handle situations like this?
I have no idea
imo that's the programmer's own fault then. don't accept a Union[Foo, Bar] in your function if they have different semantics and a Foo might look identical to a Bar, and expect to be able to differentiate those cases whether at runtime or statically
well, the issue is that the programmer might not have considered the fact that Foo and Bar could intersect, because Baz could be defined in a separate module altogether
pyright in particular has a philosophy of sticking to the safe side of things, but mypy has the same behaviour
(I think, actually, mypy doesn't do TypedDict narrowing at all, even if they're final?)
yeah and you can't override TypedDict attributes or have parameterized/generic TypedDict either ๐ฆ
class Thing(TypedDict):
thing_type: str
class ThingA(Thing):
thing_type: Literal['A']
class ThingB(Thing):
thing_type: Literal['B']
would be really useful for working with externally-derived data
then again this is where the clojure philosophy of "dont bother using types to represent the domain" comes in
you could fetch the openapi schema and wire it up to spec
otherwise you have to statically/ahead-of-time compile type definitions from the schema
(assuming the API even has a schema which 99% of the time in my experience it doesn't)
Is there some standard/good way to make a decorator work for both instance methods and standalone functions? i.e I want to support both of those:
@foo
async def thing(self, bar: Bar, baz: Baz) -> FizzBuzz: ...
@foo
async def thing(bar: Bar, baz: Baz) -> FizzBuzz: ...
I don't think it matters in most cases
As in, you don't need to do anything special to handle either case
I think?
Not sure if there are issues with unbound methods
I wish type objects supported set notation.
# desired semantics
>>> bool <= int
True
>>> "hello" in str | int
True
>>> try:
... some_horrible_thing()
... except Exception - AssertionError as e:
... # idk, but e isn't an assertion error
I don't really know what properties I want values returned by type.__or__, etc. to have, though
I just know that I want it.
though I guess it would have to be backwards compatible with whatever that operator returns in the context of type annotations.
itโs time to move to TypeScript
no
idk
is it not the case?
I think this would involve a grammar change, yes
it wouldn't
I think you can put any expression there
!e
try:
pass
except 420 + 69:
pass
@grave jolt :warning: Your eval job has completed with return code 0.
[No output]
yeah
how is this not a runtime error wtf
because no exception happens
Nope, it just checks if the exception is a subclass of each variant
ah right
and, sadly, dynamic isinstance (like with ABCs or runtime-checkable protocols) doesn't work here
that makes sense
That's a pain to handle. Look at discord.py, it has to seperate it to @commands.command(), @bot.command(), @commands.Cog.command()
It would be nice if it always returned a union, and if unions worked with isinstance the same way as tuples
Oh nice!
cool!
@paper echo I actually like your ProtocolFrom idea. It would e.g. make testing code that talks to external services easier
I'm very happy with today's progress ๐
I think I'll just write some comments and docstrings, and then I'll be ready to move on to the next thing ๐ฎ
Exciting!
pretty sure if someone can do that, they wouldn't be sharing it with others
ahaha
Hello @unkempt rock, we don't allow for recruitment here, please don't ask people to DM you
ah okay
Hi guys
Can i get a help here for my question
[[1, 2, 3, 4],
[5, 6 ,7, 8],
[9,10,11,12]
]
Print the numbers in this above 2D matrix backwards:
Output: 12, 11, 10, 9, 8, 7, 6, 5, 4 , 3, 2 , 1
Can you guys please help me on this
Why does Concatenate require that the last parameter is a ParamSpec?
Why can't I do this? ```py
def require_auth(
fn: Callable[Concatenate[P, AuthUser], Awaitable[Response]],
) -> Callable[P, Awaitable[Response]]:
...
ff?
you cant get + overloading as powerful as in julia in python, since it is a method, not a function
if i pass an argument to a function, does that go as a pointer? for example ```py
In [1]: def a(c):
...: del c
...:
In [2]: b = 444
In [3]: a(b)
In [4]: b
Out[4]: 444```, so is like the argument c holding the memory of b, and when you delete it, it deletes just the pointer and not b itself
https://www.youtube.com/watch?v=_AEJHKGk9ns I don't think I can explain it better than ned. Thinking about it in terms of pointers is not quite right.
oh
the name gets evaluated to its object and that gets a new local name bound to it
del never deletes the object directly
It removes a reference, and if that was the last remaining reference, in CPython it will get terminated immediately
is there some kind of dead code elimination algorithm that can remove "unused" variables like _hy_anon_var_1?
def hailstone_sequence(n: int) -> Iterable[int]:
while n != 1:
if 0 == n % 2:
n //= 2
_hy_anon_var_1 = None
else:
n = 3 * n + 1
_hy_anon_var_1 = None
yield n
I don't think there's anything that'll automatically remove it because of it possibly being used dynamically but I believe there is a flake8 warning for it
yeah i am willing to assume that there are no dynamic references to it
however if it could be extended to dict lookups with string literal keys, that'd be great
def eg():
_hyx_letXUffffX25 = {}
_hyx_letXUffffX25['x'] = 5
return 3
removing _hyx_letXUffffX25['x'] and subsequently _hyx_letXUffffX25 itself would be very useful too
are you trying to reverse obfuscated code? ๐
i asked a longer-form version of this on stackoverflow https://stackoverflow.com/q/68728307/2954547
nope, i'm trying to remove junk from hy2py output
the original code was:
(defn h []
(let [x 5]
3))
(defn ^(of Iterable int) hailstone-sequence [^int n]
(while (!= n 1)
(if (= 0 (% n 2))
(//= n 2)
(setv n (+ (* 3 n) 1)))
(yield n)))
@paper echo some linters can detect unused variables, maybe you could steal an algorithm from e.g. flake8? ๐
i looked in vulture's source i wasn't able to figure out what exactly it was doing. i'll see about flake 8
very interesting. fun language, although it's very unstable right now as they progress towards 1.0
it's a bit like neovim was before the 0.5 release. the last stable release is now way out of date but they're not really close to releasing 1.0 yet
it looks like i could maybe hack this by running flake8 and parsing F841 errors out of the output
https://github.com/PyCQA/flake8/blob/master/src/flake8/plugins/pyflakes.py#L56
https://github.com/PyCQA/pyflakes/blob/da197ee94e791640d82940396c19d2d82ca8defb/pyflakes/checker.py#L2162-L2167
src/flake8/plugins/pyflakes.py line 56
"UnusedVariable": "F841",```
`pyflakes/checker.py` lines 2162 to 2167
```py
def checkUnusedAssignments():
"""
Check to see if any assignments have not been used.
"""
for name, binding in self.scope.unusedAssignments():
self.report(messages.UnusedVariable, binding.source, name)```
unless flake8 has a python api
Yeah I wanted to suggest that solution, but I though we'd discuss hackless ones first
hackless would be ideal. let me see how pyflakes actually does it
it looks like it has its own algorithm for figuring out lexical scopes
no type annotations in the source code ๐ฆ
oh... FunctionScope is a subclass of dict, that's really simple and makes sense
pyflakes/checker.py lines 642 to 652
def unusedAssignments(self):
"""
Return a generator for the assignments which have not been used.
"""
for name, binding in self.items():
if (not binding.used and
name != '_' and # see issue #202
name not in self.globals and
not self.usesLocals and
isinstance(binding, Assignment)):
yield name, binding```
!e ```python
from dis import dis
def f():
if a:
return 1
elif b:
return 2
else:
return 3
def g():
return 1 if a else 2 if b else 3
dis(f)
dis(g)
@paper echo :white_check_mark: Your eval job has completed with return code 0.
001 | 4 0 LOAD_GLOBAL 0 (a)
002 | 2 POP_JUMP_IF_FALSE 8
003 |
004 | 5 4 LOAD_CONST 1 (1)
005 | 6 RETURN_VALUE
006 |
007 | 6 >> 8 LOAD_GLOBAL 1 (b)
008 | 10 POP_JUMP_IF_FALSE 16
009 |
010 | 7 12 LOAD_CONST 2 (2)
011 | 14 RETURN_VALUE
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ofivifeniw.txt?noredirect
neat, those are the same almost the same
is that sarcasm or not
not sarcasm
I guess it sort of makes sense
everything else in python is a dict
name lookups might as well be, right?
why is there an extra
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
in f?
is cpython not able to figure out that this if is "total" and that the function can't proceed past it?
i guess it makes sense that it couldn't
yeah it sometimes add that just to be sure
even if a function only contains a single if-elif-else chain
i wonder if pypy optimizes away unused assignments
hi i have a pyqt question which room should i use?
thx
the bytecode will always add a return None if it doesn't see an unconditional return, it's just cheaper than trying to figure out that all branches above it had valid returns
What's the difference between typing.Coroutine and typing.Awaitable?

are there some non-coroutines that are still awaitable, or vice versa?
Any object can be made awaitable if its class implements the __await__ dunder
so what's special about coroutines?
also, does the __await__ method have to be async?
# ----------------------------------------------------------------------------------------------
# ----------------------------- Internal Application File Structure ----------------------------
# ----------------------------------------------------------------------------------------------
# IMPLEMENTATION NOTE: bundled '.exe' application prohibit writing internally to the program.
# In order to write logs and other files, a location on the drive must be chosen. This location
# defaults to a directory known as the 'external root', and is dynamically created at:
# Windows : C:\Users\<username>\Application Support\<application-name>
# Linux : /home/<username>/Application Support/<application-name>
# OSX : /users/<username>/Application Support/<application-name>
# Many important locations used by Pyscript are relative to this directory, which cannot be
# created until after the application's name has been collected at startup. They are initialized
# with null values and are updated when the Application object is created.
# The user may supply alternative locations as needed.
Does this make sense?
why not use appdata on windows and XDG paths on linux.
๐ฎ
Really, this is the best I could cobble together not having access to a PC or a Linux machine. Just sorta grasping at whatever I can find
If you have some wisdom you'd like to pass down I'd be grateful
Which reminds me, I need to get my computer here triple bootable. I wanted to last weekend but I didn't have even a single USB drive in the house so I couldn't do linux
for linux, you should use these directories, conventionally in a subdirectory whose name starts with . https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
ye, storing files at some location is normal
for windows, use %appdatalocal% (or %appdata% if you want to sync across devices)
Is there any reason I can't just use os.expanduser('~/Application Support')?
because there are standards for where these files should go, to avoid a mess and stay compatible with non standard setups
not all users have a home, not all user homes are writable
praise
This is information I've searched for but I've never found
I've made a screen shot of the comments you've made pointing to various locations (I hope thats okay, privacy and all)
I've got my hands full with another task right now but I'll come back and pester you all for specifics regarding this when the time comes
yeah, that's fine. for linux/unix, freedesktop is what you want, but the docs on windows appdata are a bit sparse, most of what I can find is for C#, and it's a bit hard to infer what to do with that
Sorry for a rather basic question ๐
Not getting any love in my help channel
If I have, say, a bunch of styles I want to describe
class WindowStyle(Enum):
BORDERLESS: auto()
THIN_FRAME: auto()
THICK_FRAME: auto()
DARK_MODE: auto()
How do I go about exporting each individual flag? Or, do I actually call the WindowStyle class in some way?
They can be comboed
Well, most can. There are multiple types, some bitwise enabled, others containing lots of different data types
I just discovered that python has a frozenset type, I've been searching for how is it useful and the only thing I found was that it's just an immutable and hashable version of set. While this definition does make sense, what's the actual use-case of it? I can't think of any scenario where I'd want to use frozenset instead of a set, or if I needed it to be immutable, tuple, does someone here have some actual example where neither set nor tuple would be a proper type to use, but rather a frozenset would?
I have used it before for storing a set of all combinations
you can put a frozenset into a set, and a combination is not ordered, unlike a tuple
but does the fact that tuple is ordered actually prevent some usability here?
it's semantics. a combination isn't ordered, but a tuple has order
@radiant scrollwell, consider
{(1, 2)} | {(2, 1)}
#vs
{frozenset((1, 2))} | {frozenset((2, 1))}
only one of these results is correct for a set of combinations
Hmm, anyone have any tips on typing a decorator?
I have: ```py
_T = TypeVar('_T')
def test(func: _T) -> _T: ...
But this would of course allow any type through
Wouldn't def test(func: Callable) -> Callable loose all information regarding return type and arguments?
how about _T = TypeVar('_T', bound=Callable)
if you want to be more precise, you can use ParamSpec and friends (PEP 612) from typing_extensions
but, as I learned the hard way, it's not as good as in TypeScript
Hmm, I think that could work thank you
what's the typescript version?
+1 for paramspec!
does mypy support it yet? it doesn't seem to work in mypy-play
I'm having FUNNNNNNN
๐ ๐ ๐
You dudes have any awesome programming music?
Hmm, I don't even know if this is possible. But I need to type a function that will return a class. It works somewhat like this: ```py
def test(...): ... # Not sure how to do this
my_type = test(a=int, b=str)
Above is the same as
class my_type:
a: int
b: str
I have working code for runtime.. static type checkers are probably not advanced enough to understand this right?
Can't you use -> type?
Yes, but then that is simply type without any annotations.
It works kind of like a named tuple, any idea how I can hook into this?
I assume static type checkers have special cases for named tuples to support these kinds of things: Point = typing.NamedTuple("Point", [('x', int), ('y', int)])
Yep. You'll have to write a mypy plugin and just feel bad for those who use pycharm/pyright
is my_type always subclass of a known base class?
if so, you can do this
def test(): -> type[MyBase]:
...
MyType = test()
oh i see
this is for setting annotations at runtime... yeah
just use Hy tbh
who needs type checker plugins when you have macros?
Yes, primarily this class has a __setattr__ that just ensures no one sets any "illegal" attributes (attributes not specified to test()). Other than that, nothing of value.
I am not following, Hy?
that, or, we need something like Foo = Protocol("Foo", a=int, b=str), like TypedDict and NamedTuple
i was half joking, but https://docs.hylang.org/en/alpha/
lmao
i don't think you can do this with hy either, without the Protocol thing i demonstrated above
Yeah exactly, it works somewhat exactly like TypedDict and NamedTuple
Hmm, how does that work?
if you had the Foo = Protocol("Foo", a=int, b=str) syntax, you could write a macro that expanded to it, or something
Macro?
(in hy)
Ah lmao
basically, allows you to turn (...args: [...Args, HTTPReq, User]) => T to (...args: [...Args, HTTPReq]) => T (a la authentication handler). It's impossible in Python, I assume because it's somehow complicated by kwargs
TL;DR typescript treats ...args (*args) as tuple types, and this combines nicely with the ability to manipulate tuple types
it's not perfect of course, many things that make sense to a human are still missing
So does Python?
I meant in the type hint real
If you do **kwargs: int it becomes Dict[str, int]
Oh, so with the example above you'd instead do **kwargs: Dict[str, int]
in Python, *args just has a single type for all arguments (like tuple[int, ...]), whereas typescript encodes *args as a tuple with structure, such as tuple[int, str, str, ...]. And these tuple types can be manipulated in some ways
yes
Hmm, I don't know what I'd prefer honestly
it would be useful if you could do py class Kwargs(TypedDict): foo: int bar: str baz: Sequence[float] and then ```py
def f1(x: Foo, **kwargs: Kwargs): ...
def f1(x: Foo, y: Bar, **kwargs: Kwargs): ...
...
instead of repeating the kwargs or just slapping `Any`
Yeah, that would be very nice. Honestly doing it inline would be nice: ```py
def f1(x: Foo, y: Bar, **kwargs: {'foo': int, 'bar': int, 'baz': Sequence[Float]}): ...
The thing is though, at this point you should simply have: ```py
def f1(x: Foo, y: Bar, *, foo: int, bar: int, baz: int): ...
now imagine that you have 10 kwargs, and they repeat in 6 functions
I can imagine this being the explanation for the behaviour we're talking about here
like matplotlib and such
Yeah
i see, that's nice. i think i'd have preferred some method on ParamSpec like ParamSpec.concatenate, or just +, instead of the top-level Concatenate
Is is DataClass or Dataclass?
Danke
Is there any special protocol I have to follow if I want to create an abstract class designed for use as a type hint?
Like a generic or what?
I guess that's the word
Can you explain what it is some more?
Yeah
I'm gearing up to crack open and reimplement the beartype library, a runtime enforcement API
A recent addition to beartyping is the 'functional validator', lambda functions dressed up as type annotations which validate according to some kind of value check
My own implementation of this will be the 'Condition' class. It is an abstract class designed to be subclassed and its 'validate' and 'throw_exception' methods overloaded. Subclasses of this class are to be used as annotations on typecheck-decorated functions
I havn't started in on this part of the project yet, I'm just writing out a skeleton for now
But I'm wondering if there is some special protocol I have to follow for an abstract class designed specifically for typehint purposes
Now that you've explained it, I'm not really sure. I think it would be up to you to develop the type hints and the decorators to interface with one another
Thankfully I'm not really having to pull anything new out of my butt, just rearrange things a bit
But yeah. Beartype probably has some configuartion they've slaved over. I'll just inherit from object for now and get to it when I get to it
๐
๐
Help me rewriting this? I'm having a real tough time finding the right words
# --------------------------------------------------------------------------------------------------
# -------------------- Runtime Type and Value Enforcement | The Dataclass Class --------------------
# --------------------------------------------------------------------------------------------------
"""This module contains Pyscript's Enforced class, a mixin class whose objects support annotation
enforcement on a per-attribute basis."""
from typing import Any
class Enforced(object):
"""The Enforced class is a mixin class with an overloaded '__setattr__' method, such that
annotations on attributes are enforced using the enforcement API."""
def __setattr__(self, attribute: str, value: Any):
...
You might want to inherit from typing.Protocol, which makes it a structural subtype check - instead of only things that actually subclass passing, any object with matching methods is acceptable.
do you think this slice should be cached?:
In [36]: slice(None) is slice(None)
Out[36]: False
i feel like it's such a common one
or like slice(None, -1) and friends
slice is hardly ever used, so why cache it?
does "hello"[1:] not explicitly instantiate a slice?
i don't know ๐
!d slice
class slice(stop)``````py
class slice(start, stop[, step])```
Return a [slice](https://docs.python.org/3/glossary.html#term-slice) object representing the set of indices specified by `range(start, stop, step)`. The *start* and *step* arguments default to `None`. Slice objects have read-only data attributes `start`, `stop` and `step` which merely return the argument values (or their default). They have no other explicit functionality; however they are used by Numerical Python and other third party extensions. Slice objects are also generated when extended indexing syntax is used. For example: `a[start:stop:step]` or `a[start:stop, i]`. See [`itertools.islice()`](https://docs.python.org/3/library/itertools.html#itertools.islice "itertools.islice") for an alternate version that returns an iterator.
I suppose the issue with caching slice None is that slice(1, None) is different, and so on
Which means that slicing is common sure, but slice None not so much, perhaps
i don't know which slices are most common, but my guess is :, ::-1, :-1 , 1:
That seems like a good guess to me
there does seem to be some (very small) overhead:
Python 3.9.4 (default, Apr 8 2021, 21:58:31)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.24.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: text = "hello"
In [2]: %timeit [text[1:] for _ in range(1000)]
123 ยตs ยฑ 4.68 ยตs per loop (mean ยฑ std. dev. of 7 runs, 10000 loops each)
In [3]: s = slice(1, None)
In [4]: %timeit [text[s] for _ in range(1000)]
111 ยตs ยฑ 3.47 ยตs per loop (mean ยฑ std. dev. of 7 runs, 10000 loops each)
In [5]: assert [text[1:] for _ in range(1000)] == [text[s] for _ in range(1000)]
12 microseconds over 1000 operations is pretty small, i can imagine why they didn't bother with interning/caching slices
Aye, I think it's probably just not used enough in a single code base to make it worth it
