#internals-and-peps
1 messages Β· Page 57 of 1
When you return 5, 10 you're returning a tuple. When you a, b = foo() you're unpacking the returned object.
@pseudo cradle
Mindboggling
def multi_arg_func(a,b,c):
print( a + b +c )
return a, b, c
myTup = (1,2,3)
d, e, f = multi_arg_func(*myTup)```
Like, that's so cool that that works
I don't know how I'm ever going to code anything again in C++
!e ```python
first, *rest, last = 1, 2, 3, 4
print(first, rest, last)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
1 [2, 3] 4
!e ```python
def n_element_list(n):
return list(range(n))
a, b = n_element_list(2)
print(a, b)
a, *others, b = n_element_list(50)
print(a, b)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | 0 1
002 | 0 49
Very nice
also kinda mind blowing that the tuple it returns isn't required to conform to one particular shape, and different types of unpackings might be valid on different calls.
a, b = n_element_list(N) will fail at runtime unless N is 2.
Now, what about a, *others, b = n_element_list(2)?
that's fine, others will be an empty list.
...nice
but that'd fail with N=1
!e ```python
a, *rest, b = range(2)
print(rest)
a, *rest, b = range(1)
@raven ridge :x: Your eval job has completed with return code 1.
001 | []
002 | Traceback (most recent call last):
003 | File "<string>", line 3, in <module>
004 | ValueError: not enough values to unpack (expected at least 2, got 1)
donβt quote me but i think *_ ignores the elements when declaring multiple variables
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
[1, 2, 3, 4, 5, 6, 7, 8]
What's the convention over here regarding decorators?
Say I have a decorator that can be used with or without arguments. Then is it normal to use if statements to allow the decorator to be used with or without braces?
how else could you do it?
Seeing Discord.py that isn't really the case. @commands.Cog.listener() doesn't expect arguments but @commands.Cog.listener doesn't work.
right - you don't get that for free. it's easy to make a decorator that doesn't take any arguments, it's a bit harder to make a decorator that takes arguments, and it's harder still to make one that can be used either way.
how else could you do it?
@raven ridge i.e.if args are present return wrapper else return decorated function/class.
That's using an if statement
right - you don't get that for free. it's easy to make a decorator that doesn't take any arguments, it's a bit harder to make a decorator that takes arguments, and it's harder still to make one that can be used either way.
@raven ridge at the moment all of mine can be used both ways. But is this conventional/accepted?
Or is it better for a decorator that could have arguments to symbolize that by using a wrapper?
a lot of major libraries allow things taking only optional arguments to be called both ways. I'd probably do it if I were designing a class like that. But it's by no means required; it just may make things easier for your users.
the fact that @foo() and @foo work drastically differently is something that the author of the decorator knows, but the user might not, so users may be confused why the former works and not the latter if you don't make both work.
or you could sidestep it by requiring at least one arg π
Makes sense! So there's nothing essentially against allowing @foo() and @foo is what I'm hearing? Of course it always ends up requiring me to use a factory function or class but that isn't too bad given the usability advantages. I just wasn't sure if maybe @foo was outdated syntax or something.
no, there's no reason not to expose both if you don't mind doing the extra work - just make sure they actually do the same thing.
it'd be incredibly confusing for users if you decided to make @foo and @foo() both work but do something different π
βπ½ Definitely agreed on that one. Thank you for the feedback! I'll keep doing things this way then! π
Is this weird?
from typing import NewType
FooType = NewType('FooType', object)
I want to make a type only for type checking later down the line
The example I saw was always using something like , int) or , str), never just inheriting from object
I remember some pep that defined how to mark some arguments as keyword only and some others as positional only. Could anyone link it? Google's failing me
I believe these are the ones:
https://www.python.org/dev/peps/pep-0570/
https://www.python.org/dev/peps/pep-3102/
Thank you, @languid dagger !
hello, is there any active community for PyQt in discord?
the list index is out of range , can someone help me?
this isn't a help channel (see the topic) check out #βο½how-to-get-help @manic river
this isn't a help channel (see the topic) check out #βο½how-to-get-help @manic river
@lost nexus thanks
is there any way to check if a memoryview has been released? (either in python or in C)
#define CHECK_MBUF_RELEASED(mbuf) \
if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \
PyErr_SetString(PyExc_ValueError, \
"operation forbidden on released memoryview object"); \
return NULL; \
}
hmm this is what C has
So, uhh... I've been doing something with the descriptors and data models which seems to be going alright, but unfortunately my Sphinx documentation isn't loading any documentation for members that use that class I made. Does anyone know where to do the update_wrapper(...) stuff to get the documentation working?
>>> from enums import Flag, Order, StrFormat
>>> class Perm(StrFormat, Order, Flag, auto_on_missing=True, start=0):
... Z, X, W, R
...
>>> Perm.Z
<Perm.Z: 0>
>>> Perm.X | Perm.W | Perm.R
<Perm.R|W|X: 7>``` working on my enum implementation, and keyword arguments in `meta_cls.__prepare__` and `meta_cls.__new__` are pretty useful! :D
@red solar flags don't seem to be exposed to python, so best thing would be to attempt some operation on it I guess
yeah im writing a proposal for some modifications (additions) to memoryview
def is_released(memory: memoryview) -> bool:
try:
memory.readonly
return False
except ValueError:
return True``` this can work, but yeah, better add some boolean like .released
aww drat this means i'm gonna have to write unit tests :/
heheh
if i'm adding a macro like #define PySomething _PySomething, i don't need to write tests right?
oh boy it's time to write tests oh FUUUU
Is there any way to convert a list to an integer?
lol
and yes
depends how you want to interpret it tho
you want the length of the list to be the value of the integer?
x = ["1", "2", "3"]
y = [int(z) for z in x]
(but also this isn't the channel to discuss this - #python-discussion or a help channel would be more appropriate)
K thanks
@shy belfry can you give an example where sphinx fails
i managed to crash sphinx over and over in my last project
but a less severe example of sphinx failing is with generic functions because it really isn't a fan of reaching into a function wrapper and using that doc string with typehints
you end up with loads and loads of identical docstrings which wastes space
unless you do ```py
my_docstring = """..."""
for f in [f, g, h]:
f.doc = my_docstring
Hello. I am new to Discord.. Do I ask a Python question here?
is there such a thing as a profiling context manager to see how long a subset of a script takes to run line by line?
can a standard profiler not do that?
@red solar i've no idea, i've only just used %lprun for the first time
%lprun -T <log file> -f <function name> <function with args>
oh you're doing this from the command line :/
The pycharm profiler is pretty good, it can draw a hierarchical tree graph showing how much time each function call took
I don't have pycharm :/
it's an ipython magic thing
oh no
whats ipython?
oh jupyter notebook stuff
you should be able to use cProfiler in ipython?
oh wait it is cprofiler (sry this is the first time i'm looking at profiling)
@magic python you want more precise profiling than per function?
@red solar just learnt about exec so am going to try that now, I need it line by line really, unless by "per function" you're referring to something else ( i want to see how long each call to pd.crosstab or whatever is taking )
import cProfile
with cProfile.Profile() as pr:
# ... do something ...
pr.print_stats()
this is an option (but it's just pure python)
if u wanna see how long each function call takes, the profiler should be showing you that already π€
I'm just trying with quotes - profile.run( "f(x)") instead of .run( f(x) ), seems to have worked thanks
it's much more detailed than lprun actually
i'm fairly sure lprun uses it in the background
however i still strongly recommend pycharm if u can get it
profiler is just a button and it shows u everything
no setup
i feel as though I've done th setup now, what's the main thing pycharm offers over this line by line output of profile?
Benefits of an IDE π³
although saying that, 99 0.000 0.000 0.001 0.000 base.py:729(__array__) isn't that clear I guess
neat
only issue is if you have stuff that takes less than 1ms, it doesn't really count it (gives it 0% of the time)
oh that's cool, I didn't find this button and instead just used cProfile like normal
apparently profile.Profile is used for more granularity than profile.run, what if you want less π
hrm, i wonder how lprun does it - the output from that just shows me code that I wrote, whereas profile.run shows me everything, base.py and core files and all sorts, I don't really need to see those, I just want to see my lines
https://stackoverflow.com/questions/3927628/how-can-i-profile-python-code-line-by-line
seems that lprun is what people suggest for that usecase
I've been using cProfile to profile my code, and it's been working great. I also use gprof2dot.py to visualize the results (makes it a little clearer).
However, cProfile (and most other Python pro...
kernprof -l -v main.py from https://stackoverflow.com/a/62382967/3130747 was useful if it's of interest @red solar
@red solar yeah - the default output of profile.run was (for me) a bit much
also profiling is more a C++ thing for me than python - never profiled python before, i just try to make stuff readable
well I'm estimating that this module will take 8 hours to run so I'd like to reduce it if possible lol
π running my code
What kind of monster did you create π
at this point shouldn't you be writing it as a C extension?
Cython? I've considered it - or passing some stuff to Go / Rust or whatever (neither of which I know anything of)
but?
well but idk what i'm doing I guess
Before changing languages, I'd try to address the code itself. Are there any bottlenecks or things to optimize
that's why I was profiling, never really used it as a workflow before but thought I'd have a look
scipy already makes extensive use of the CAPI for computational work so the benefit of writing it purely in C or another compiled language is only going to affect the pure python gluecode, which should already be minimised
I see. Can you break the whole code down into a smaller chunks?
Profile a smaller chunk
yeah - i can profile a representative sample of the task and try and improve that, all good
Sounds good.
Python build finished successfully!
The necessary bits to build these optional modules were not found:
_bz2 _dbm _gdbm
_hashlib _lzma _sqlite3
_ssl _tkinter _uuid
readline
To find the necessary bits, look in setup.py in detect_modules() for the module's name.
So this stuff is optional, and not having it should be ok
ssl is often needed.
shouldn't be for this tho
from _lzma import *ModuleNotFoundError: No module named '_lzma'
== Tests result: FAILURE ==
1 test failed:
test_zoneinfo
how do i report this? like should lzma just not be part of the final product if _lzma doesn't exist?
and does this need to be fixed before i can submit a completely unrelated proposal? (wanna add 2 macros and corresponding documentation to the c-api)
(the test fails on origin/master before i make any changes)
Hello! :)
Is there someone very experienced in programming with Python who also invests in stocks?
Because I have a very odd concern that I'd love to talk about privately with him/her, it won't take much, not more than five minutes I swear!
This is definitely not the right channel. I would suggest off-topic channels or #python-discussion.
does dict.items() return a list or a tuple of items in a dict
@modest hatch This is not the right channel. Please read the channel description and check out #βο½how-to-get-help
dict.items() returns an iterable object containing tuples.
okay thanks
tfw you search for something, and you want the python result, but google only gives you c-api results π’
https://docs.python.org/3/library/stdtypes.html#memoryview.release does this automatically call https://docs.python.org/3/c-api/buffer.html#c.PyBuffer_Release for you? (i think it does, but the wording isn't explicit enough for my liking)
sorry bad question - it does automatically call it
what i should have asked, does the documentation make it explicitly clear enough that it does?
How my code worked even if it was wrong. (It's already fixed by others coders)
Luck
@light ember This channel isn't for that type of discussion. Please read channel descriptions before proceeding.
@low lagoon isn't my question related to design?
I mean I asked questions in #general but it's too fast for people to see
this channel is more concerning the design of the language, or advanced language concepts, not just normal code
@grizzled vigil any chance you're free to walk me through contributing/making a PR to cpython? (like an overview, not in depth - just wanna see if i missed anything)
https://devguide.python.org/pullrequest/ been reading this
any PyQt community here?
I need help with my python code
any suggested place from where to learn python (with practice tasks) ?
People like https://www.w3schools.com/python/default.asp I think.
though not really the right channel, now that I notice. π
ty
tho careful w3schools sometimes messes up on code but thats how i learned a bit c++
I started as C++ programmer and when I saw most of the concepts like vector etc are used from python, I switched to python and never turned back since haha, I don't mind if its slower than C++ but I just enjoy building code in Python π I wish 95% of the programmers on this planet just switch to Python and enhance it rather than spend time on building other languages etc.
@marsh shoal Amazing place to start is thenewboston python youtube videos; Bucky Roberts is a legend !
This bothers me more than I should and I know I've already mentioned this, but I really miss ++ and -- in Python
Start using +=1 in C++, too π
This bothers me more than I should and I know I've already mentioned this, but I really miss
++and--in Python
It's very easy to go wrong with those, whereasvar += 1andvar -= 1is explicit and easy to reason about
When I'm using other languages I really miss if a < b < c: as a shorthand for if a < b and b < c: - that's an incredibly nice quirky Python feature
Yeah, that's fair
@last pollen Why is it easy to go wrong with those?
Seems pretty intuitive and it's so much fewer keystrokes
That if a < b < c syntax needs to be in every language as of yesterday
Postfix increment vs prefix increment is fairly confusing. And the syntax for overloading postfix increment in C++ is a glaring hack in the language specification
Two of the same keypress is just so much sweeter than the mess of presses all over the keyboard that is the equivalent
how often do you do var += 1?
My Java instructor said to never use prefix ++, but it seems way less confusing conceptually than postfix
+= is also immediately obvious to a lot of people
I rarely even use ++ and --
I forget, what are some situations in which prefix and postfix increment / decrement would behave differently?
*(++x) = 5; means x += 1; *x = 5;
*(x++) = 5; means *x = 5; x += 1;
I would prefer += as well since it's much more readable than prefix/postfix syntax
def printLines(line):
numTimes = int(input("Number of repetitions?"))
for i in range(numTimes):
print(line)
return numTimes
could someone explain to me line 2 and why it is return numTimes
!e ```py
a, b, c = 1, 2, 3
print(a < b < c)
@torpid bridge :white_check_mark: Your eval job has completed with return code 0.
True
Python has it.
Oh what @raven ridge you confused me :/
He was saying he misses this in other languages
Ohhh I canβt read
Good to know π
Thought it was a little suspect python supported one but not the other
i think it's weird that in and not in are also considered comparison operators
and therefore chainable
cant really see any practical benefit to it either
like what's the chance you have to do this?
>>> 2 in [2, 3, 4] in [[2, 3, 4]]
True
>>>
it also opens up the door to weirder and potentially confusing stuff like this
>>> 2 in [2, 3, 4] < [4, 3, 2]
True
>>>
If you want to write bad code, no one can stop you π
I'd be shocked to see anyone write stuff like that
given that all those can be defined by magic methods, there may exist some nice case where these expressions come up
>>> 2 in [2, 3, 4] == True
False
i could see a beginner making this mistake
Oh beginners mess up chaining in general, that can always happen
@deft pagoda
true. still though, having membership checks in the same category as comparison just feels strange to me.
just from a language design point of view
That's because of CPython internals
this goes beyond cpython. it's part of the python language specs.
It was easier to make it a comp_op
I think the impact of trying to stop someone from shooting their own foot on everyone else writing sensible code with unnecessary checks is significant enough to merit pythons stance of simplicity
Keep it simple. Assume people use things sensibly. Leave it at that
I mean, that is just good sense, nobody should try to chain those, or at least I don't see a reason to do so
Itβs nice that itβs there if someone finds a good reason tho π
It is okay to allow weird things to be done if nobody would do that
Well the reason is simple. Chaining, in general, is awesome.
Yeah, that's a really cool functionality
So, you write logic that implements this awesome feature. And then you notice that it can be used in not-so-awesome ways. This is the point where you decide : is this edge case significant enough to make an explicit check for it, taking a performance hit for every time chaining is used? Or not. That's it.
Python often leans towards "consenting adults" mentality in these cases.
In chaining in particular, I agree with the design choice.
hmm, it seems that ifyou return an arbitrary value from __contains__ it gets converted to a boolean
does python not want to run multiple instances of the same script?
maybe if in/not in had different precedence to ==/>=/<=/and so on that'd be a better middle ground.
I don't think python cares one way or another.
I opened a second window of a working script and it did absolutely nothing
Hmm
not associative:
In [38]: 1 in [1] in [[1]]
Out[38]: True
In [39]: (1 in [1]) in [[1]]
Out[39]: False
In [40]: 1 in ([1] in [[1]])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-c04eb8a4d4b0> in <module>
----> 1 1 in ([1] in [[1]])
TypeError: argument of type 'bool' is not iterable
yep they are actually considered comparison operators
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!=" | "is" ["not"] | ["not"] "in"
yeah, i would probably chain these in certain mathematical code
@naive hawk this isn't a help channel
oh sorry but where it's ?
thx ^^
I find it weird and honestly upsetting that in force-casts the output of __contains__ to a boolean, when == and other comparison ops do not
i do too, i think it should either raise an error or just allow anything --- like __len__
I'd rather go with allowing anything to keep it in line with the other operators (and allow for some creative, albeit not exactly practically useful code)
why is it upsetting that it force casts it to a boolean? __contains__ is supposed to return a boolean anyway
^
In the absolute majority of cases it doesn't matter, but it is technically limiting
You could say the same about any other comparison operator really, they're all supposed to return a bool
i am kinda new to python and i was just wondering how can you find the mode(most occuring number) and the median(mid value) from a set of inputs. thanks in advance
For the first, I'd use collections.Counter, then take the key with the highest value.
For the latter...not sure there are easier methods than sorting the array and taking the middle element.
there's bound to be a statistics library that can do all these, too
scipy probably can, maybe pandas too.
Also, just realised - this is #internals-and-peps, not #python-discussion or a help channel. It's rather specialized π You might want to check #βο½how-to-get-help instead.
the statistics module provides functions for both
oh, of course stdlib has a statistics module π©
Python syntax vs Kivy or Flask...
What is a examples of ONLY PYTHON CODE vs Kivy code or Flask? Things that IS PYTHON, vs a add on
what?
Flask is only python code
Kivy is a gui module
flask is a web framework
your line of question is a bit squiffed
@strange fog I agree, the 1 in {0,1} in {0,1} being False made me heavily scratch my head, it's not obvious at all
is that actually valid syntax? lol
apparently yeah, expands into 1 in {0, 1} and {0, 1} in {0, 1}
Yes, because in, just like < > <= >= == !=, is treated as a comparison operator
Huh
just like other chained comparison operators
That's.... huh
That's jank
ya lmao it seems so boilerplate
The output of __contains__ is also force-casted into a boolean if it's not invoked directly, unlike probably every other operator
eq, lt and the rest of comparison gangβ’ doesn't get forced into a boolean
but contains does
That's so friggin weird
But only if you do in, if you invoke A.__contains__ directly it returns 42 as expected
I THINK I might know why?
Why would that be?
does it matter if it's a standalone expression vs when used in an if?
no
Well, for the regular comparison ops, we can look at pathlib for why they might want you to customize what the symbols do
Example being they changed the division symbol from being, well, division to concatenating the paths together
Well, division is a general-purpose operation
But in is one of those situations where it's explicitly going to have to be a boolean. Much like how we typically want to do is_even() or something when writing functions
It's expected
But I'm also just pulling this out of thin air, sooooo
And why wouldn't it be expected for == or < π€ ?
i could imagine returning some weird 'maybe'like value for ==
to get approximate equality
if you want to get weird :p
Isn't ~= technically already a thing
Shhhh
oh
I forgot that it was
yes
wait no
don't think it is, the other binary operators have assignment tho, it isn't in 3.7 at least
Was going to say, I didn't think I'd seen it before
i think there was a pep for it though
My brain is lagging, mb
at some point
There's also an undocumented operator for extracting the value from a single-value container.
,=
!e
x = [42]
y ,= x
print(y)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
42
:)
oh wow
Thanks, I hate it
I'm going to find some use for this
trailing commas are confusing
that doesn't work
nope
Can't use starred expression here
So duuuumb
w o w
what if it doesn't support indexing
of course
wasnt there a thing about not being able to unpack in return values either?
without an explicit tuple
It just forces the left-hand side to be a tuple of one element, it's a trailing comma
thing that got addressed at some point
My brain hurts
yes it's a secret operator,= is like x --> 0 in C, it's just abusing the spacing to make it look like something else
You might call it a smooth operator
It's a double-barrel sawn-off
print(βUwUβ)
,=
UwU
@unkempt rock Is there a reason you keep spamming that here?
no
Then I would ask that you don't
uwu?
As in don't interrupt an active conversation if you have nothing to contribute to said conversation
def example_2():
items = [1, 2, 3, 4]
return 0, *items
yep looks like this got fixed in 3.8. 3.7 and below youd get a syntax error on the return line
That's funky
Ok, so what would you deem more readable, [y] = x, y, = x, (y,) = x or y ,= x?
[0] and [2] are the most explicit it seems, [1] looks less noisy but still readable, [3] looks like something you'd use to impress others
It's weird to me that [0] still works on ones that aren't lists
I mean I know that's probably silly
That's a fair point tbh
none of the above. y = x[0] all day :p
Type {InsertName} is not subscriptable
(as I got pointed out to me earlier)
ah yes i was busy looking up the return unpacking error thing
Interesting thing
didnt see that part of the convo
No no, I was more just saying I was wrong, too
So if you do [y] = x where x is a dictionary, it'll give you the key
petition to make generator subscriptable? π
And just the key
or all iterables rather
if they dont have indexing just iter() + next until you get the desired value
internally
On a side note, the return unpacking is still funky in 3.8
oh is it
>>> def func():
... return *(i for i in range(5))
...
File "<stdin>", line 2
SyntaxError: can't use starred expression here' # because discord markup doesn't like me
>>> def func():
... return -1, *(i for i in range(5))
...
>>> func()
(-1, 0, 1, 2, 3, 4)```
oh dear
at first glance, i could swear you're returning a pointer lol
yeah that doesnt work in 3.9 either
idk why I went with i for i in range(5) instead of just *range(5)
small brain moment right here
!e
x = [42] y ,= x print(y)
@grave jolt How do you type the text with the rectangular outline and opaque background?
!code
Discord has support for Markdown, which allows you to post code with full syntax highlighting. Please use these whenever you paste code, as this helps improve the legibility and makes it easier for us to help you.
To do this, use the following method:
```python
print('Hello world!')
```
Note:
β’ These are backticks, not quotes. Backticks can usually be found on the tilde key.
β’ You can also use py as the language instead of python
β’ The language must be on the first line next to the backticks with no space between them
This will result in the following:
print('Hello world!')
Thanks
speaking of < >
!e
class _AppliedOperator:
def __init__(self, value, fn):
self.value = value
self.fn = fn
def __gt__(self, other):
return self.fn(self.value, other)
class CustomOperator:
def __init__(self, fn):
self.fn = fn
def __gt__(self, other):
return _AppliedOperator(other, self.fn)
approx = CustomOperator(lambda a, b: abs(a - b) < 0.001)
print(0.123456 <approx> 0.123457)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
<__main__._AppliedOperator object at 0x7f172481d490>
I don't understand the output
it should be True
And actually, (0.123456 <approx)> 0.123457 is True
and and or return the operand that matches its truthiness by short-circuiting the logic
Although I do have to compliment the <opname> idea, it's really creative
I stole it from a stackoverflow answer on C++
Ah, SO strikes again
!e
_STACK = []
class CustomOperator:
def __init__(self, fn):
self.fn = fn
def __gt__(self, other):
if len(_STACK) % 2 == 0:
_STACK.append((self.fn, other))
return True
else:
fn, left = _STACK.pop()
return fn(left, other)
approx = CustomOperator(lambda a, b: abs(a - b) < 0.001)
print(0.123456 <approx> 0.123457)
avg = CustomOperator(lambda a, b: (a + b)/2)
print(1 <avg> 4)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
001 | True
002 | 2.5
I'm definitely stealing appropriating <opname> for my hobby projects, that's really neat
what would you think about a total comparison operator like <=> which would return LT EQ GT, either as constants like True/False or -1 0 1?
something like https://docs.python.org/2.7/reference/datamodel.html#object.__cmp__ ?
it would be kinda nice. Currently, it's mostly possible with something like sgn(a-b) if they are number-like, or some ifs if not.
that symbol I just took from C++
I don't see any use for that, to be honest
can i activate .py files from pressing a button in tkinter?
@unkempt rock This isn't a help channel. Use #βο½how-to-get-help to acquire help, and remember to read channel descriptions.
okay
a = [1]
b ,= a
why does this exist

more importantly, how did you find out about it
intresting ```>>> a = [1]
b ,= a
b
1
a
[1]
huh, neat
more importantly, how did you find out about it
our staff team has connections to the CPython core development team
interesting little tidbit that i'll forget by tomorow but interesting nonetheless π
thanks, makes more sense now π€·ββοΈ
the lack of paranthesis does things to your brain
the amount of times i accidentelly added a , at the end of a variable assignment π
it's also a bit odd to have the comma next to the equal sign
a parsing oddity indeed
yeah, ,= sounds like it should do a ,=b == a = a,b
like, it's how the other <something>= operators work.
, isn't an arithmetic operator though, but that would definitely be interesting
a = input('>>>')
b = {'.'}
if a == 1:
del(b[0])
b[0] = '1'
print(b)
why doesnt it update?
this isn't a help channel, #βο½how-to-get-help
i can tell you that you will need to do a=int(input()) though, as input() will always be a string
Why does Pep8 hate camelCase?
I feel like it wouldn't be the worst thing to use camelCase either for function names or variables
and leave snake_case for the other
Fuck it. I'm using camelCase for my vars
I find camel case a bit odd tbh
like i dislike it because its not consistent with caps which annoys me having the lower starting letter and caps for each remaining
I can kind of go either way
I think after doing Python for so long, my brain hesitates when I have to do camelCase and I end up taking longer to write it than pipe_case
Despite it being technically longer
I also just like having vars/arguments be separated stylingwise from functions/methods but maybe that's just me
Some people write functions/methods in PascalCase, and it drives me crazy a little bit
camelCase looks kinda ugly to me, I prefer snake_case or PascalCase
personally I prefer kebab-case or
`allowing spaces in identifiers come on its 2020 not 1950`
eh, mostly you just kinda adapt in time with whatever code base you're working on
true
But mentally you're going "man, I wish it was this"
And hopefully the codebase adheres to the convention of built-in names.
if i would see a camel case codebase in python it would probably make me anxious π
but the less time you use to argue about personal styling conventions, the better
@grave jolt File "<ipython-input-5-ec7702362b26>", line 1
pygame (test)_STACK = []
^
SyntaxError: invalid syntax
had a particular short internship, where alot of the code interviewing being done was based heavily on personal stylistic preference
You copied it incorrectly @random path
wasn't the best experience
i find pep8 a godsend, adhere to the language standard and it's readable, ciao
Most cognitive dissonance I had was in C&&+Qt.
Legacy C names are written in withoutseparatorsandvwls-case like wcsxfrm
C++ names are in snake_case
and Qt names are in camelCase
I have a question I REALLY need an answer to.
How different is Ada language from python?
wow...
isn't ada a provable correct dependent typed language?
the only part of that sentence that applies to python is "language"
In plain English that means....?
Very
hey what if you'd write identifiers like $my identifier$ (spaces are allowed) and it'd be a convention for every IDE to just remove the $ signs and turn the identifiers into bold text
probably would be annoying for the visually impaired
how would you unbold something?
@red solar e.g. placing the cursor in front of an identifier and pressing backspace
also why?
@red solar to cater to the demands of "special characters make code less readable" and still making identifiers easily recognizable
Representing code as plain text might be a legacy idea we're not willing to rethink.
It requires us to resort to hacks like escaping with \.
who's putting special characters in their code? wtf
if i see emoji characters in any code i read, i'm going to get angry
special characters are characters that are not alphabetical or numerical characters or punctuation
not just non-ascii characters
what about ligatures?
but why are these (non ascii chars) in the code in the first place?
They are allowed in variable names.
well, many of them. Not, say, emojis, but katakana is fair game π
that doesn't mean people (should) use them
they were probably allowed to help with writing code in other languages
in which case it would be readable to anyone who knows the language
I don't see a valid reason to allow special characters in variable names.
I once had a mysterious bug where I wrote
!charinfo Ρ
\u0441 : CYRILLIC SMALL LETTER ES - Ρ
\u0063 : LATIN SMALL LETTER C - c
also
!e
FΠ°lse = True
TruΠ΅ = False
FΠ°lsΠ΅ = FΠ°lse
FΠ°lse = True
print(False, FΠ°lse, FΠ°lsΠ΅, TruΠ΅)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
False True True False
what the fuck
Why are True and False allowed to be var names
they aren't
!charinfo FΠ°lse
\u0046 : LATIN CAPITAL LETTER F - F
\u0430 : CYRILLIC SMALL LETTER A - Π°
\u006c : LATIN SMALL LETTER L - l
\u0073 : LATIN SMALL LETTER S - s
\u0065 : LATIN SMALL LETTER E - e
\u0046\u0430\u006c\u0073\u0065
it is not False, but FΠ°lse
oh
I should've guessed
I've been using that to bypass chatfilters for a loooong while 
https://www.reddit.com/r/rust/comments/5penft/parallelizing_enjarify_in_go_and_rust/dcsgk7n/ sorry back to the special characters thing, i forgot to link this
!e
import unicodedata
print(unicodedata.normalize('NFKD', '\u0046\u0430\u006c\u0073\u0065'))
@paper echo :white_check_mark: Your eval job has completed with return code 0.
FΠ°lse
π€¦ not sure what i expected
!e
import unicodedata
print(unicodedata.normalize('NFKD', '\u0046\u0430\u006c\u0073\u0065').encode('utf-8'))
@paper echo :white_check_mark: Your eval job has completed with return code 0.
b'F\xd0\xb0lse'
hm. interesting implications for language design
even if you force variable names into NFKD you don't solve the problem entirely
what if we had something like IDN for variable names
xn!flse_53d = 10
assert locals()['\u0046\u0430\u006c\u0073\u0065'] == 10
something like this, idk what the syntax would actually be
then again nooobody wants to write punycode variable names by hand
nobody wants to read this horror either π
You know how you can get a function's signature with inspect? Is that an attribute of the function object itself?
I think I tried finding it once with dir and didn't see anything interesting.
it is in function.__code__ somewhere afaik
yep f.__code__.co_*
I wonder if it was something like function.__sig__, would that result in poorly conceived meta programming?
oh f.__annotations__
if type hints were used, you can also see __annotations__
In [68]: def fun(a, b, c): ...
In [69]: fun.__annotations__
Out[69]: {}
In [70]: fun.__code__.co_argcount
Out[70]: 3
that's not as fun as all the information you get from inspect
In [74]: def fun(a, b, c):
...: d = a + b
...: return e
In [75]: {k: getattr(fun.__code__, k) for k in dir(fun.__code__) if k[:2] == 'co'}
Out[75]:
{'co_argcount': 3,
'co_cellvars': (),
'co_code': b'|\x00|\x01\x17\x00}\x03t\x00S\x00',
'co_consts': (None,),
'co_filename': '<ipython-input-74-a5ec6893f41b>',
'co_firstlineno': 1,
'co_flags': 8259,
'co_freevars': (),
'co_kwonlyargcount': 0,
'co_lnotab': b'\x00\x01\x08\x01',
'co_name': 'fun',
'co_names': ('e',),
'co_nlocals': 4,
'co_posonlyargcount': 0,
'co_stacksize': 2,
'co_varnames': ('a', 'b', 'c', 'd')}
```this is all you get
π€―
ok so after a lot of research i have come to conclusion i have no idea how bits work in python.
def LAST_BITS(k,n):
return ((k) & ((1<<(n))-1))
def BitSlice(k,m,n):
return LAST_BITS( ((k)>>(m)),((n)-(m)) )
SHA256="d632b3049081b413ecceed6fb80d56657b1c43a51ecad3e5ad02a6e720eced01"
BitSlice(SHA256,120,136)
this however returns various errors depending on if i pass it a "string". how do i convert this hex string to a malleable set of bits to i can return a subset of them?
def LAST_BITS(k,n):
return ((k) & ((1<<(n))-1))
this takes and returns an int.
The string you can parse as a hexadecimal int if you really want.
In [90]: int("d632b3049081b413ecceed6fb80d56657b1c43a51ecad3e5ad02a6e720eced01",16)
Out[90]: 96884527485712115404056311403563845911353878330075242211070609857748849716481
ah ok i thoughts that where i went wrong.
ValueError: invalid literal for int() with base 10: b'\xd62\xb3\
casting the hex string litterally just gives me an error tho
not sure how to work with bytes like you want, though.
If you want bit sequences, your options are int or bytes or byarray
str is a sequence of Unicode characters, not of bits or bytes
O_e but at some level they are all just bits at heart
Yes, but not at a level you should be accessing.
lol indeed. trying to convert them over to a 16bit number for a color
Ye, use an int as per ConfusedReptile
thanks guys for the input π ill try that Reptile and see where i get. its been a frustrating night. but i think thats what i was missing
is there a way to print all characters (including hidden) its working as expected in a stand alone environment but the minute i pull the hashes from a sha256sum.txt file its giving me an invalid litterall. the only thing i can comeup with at this point is im passing unsensitized data thats not in the hex string format thats expected
you can just print it, or print(repr(text))
wow lol it may be time to take a break for a while. i just found hash = bytes.fromhex(hash_str) this just hanging out causing issues. its always the details the get you. >..<
BINGO π thank you ConfusedReptile thats exactly what i did wrong. ^ i had that in there trying to work around the problem and forgot to take it out.
i cant type in #python-discussion
Yes you can
This is the wrong channel
How do I run a function of a class, inside a different class?
ClassName.functionName doesn't seem to work
do you have an object of the other class?
anyone using Python 3.9 Beta?
@near coral I have used it in tests
@vivid crow Can you show us the code you are worrking with? What is "the other class"?
oh nice
I am interested in this new parser they will be releasing
although i don't fully understand the documentation for it
i haven't looked into that at all
it's practically done. rc1 is slated for aug 10th or something
oh wow
I might install the release candidate then
Hoping to test this out. I have my own function for this, but I trust python's more for removing prefixes and suffixes within a string
So when you import a module, that whole module gets run, even if you're only importing certain objects, yes?
And subsequent imports don't cause the module to be re-executed? How is this managed as far as the reference count?
@worldly venture
!ban 734970770333368406 Low effort troll
:incoming_envelope: :ok_hand: applied ban to @grizzled basin permanently.
:incoming_envelope: :ok_hand: applied mute to @gaunt light until 2020-07-21 04:01 (9 minutes and 59 seconds) (reason: mentions rule: sent 11 mentions in 10s).
Is anyone available tomorrow to help me on my collage python course?
Im falling behind cause I cant seem to add things together π€¦π½ββοΈ
@boreal umbra yes, that's correct. The first import adds the module to sys.modules, and the next time it's imported the existing module that's in sys.modules is returned instead of reexecuting the module's code
@velvet fossil you can get help with school-related work in the help channels as long as you're focusing on learning things conceptually; you can't get code written for you here.
@boreal umbra thanks for letting me know, yeah exactly what im in need of, as long as I understand the concept I'd be able to get the work done
As far as reference count goes, the module itself is an object with a reference count. Import it once and it has a reference count of 2 (you're holding a reference to it, and so is the sys.modules dictionary. Import it again from another module and the reference count goes up to 3
@raven ridge is sys.modules in part for ensuring that each module has a non-zero reference count?
@unkempt rock take a look at #βο½how-to-get-help
ok
It's for caching already-loaded modules so that they can be reused...
So, yeah, I guess you could put it that way
I said "in part" since caching them would presumably be the primary goal.
Yep.
But caching them necessitates keeping them alive, so there's a reference held to make that happen
I suppose that also means that manually deleting an element from sys.modules doesn't guarantee that it will be reloaded if you try to import it again, since it might still be alive via another reference.
(Not that you should write code that depends on modules being reloaded.)
Au contraire - if you delete it fromsys.modules the next import will search for and load the module again.
And, if someone still had an existing reference, now you've got two different copies of that module used by different modules.
π€―
When import is doing it's thing, it checks in sys.modules to see if it's previously been loaded, but if it's not found there, it doesn't have any way to know that it was already loaded
There's not some other cache it can check, nor can it reasonably inspect every object to see if it refers to that module.
Makes sense
And if you do manage to get 2 copies of the same module loaded things can break in surprising ways, so, ya know, try to avoid it π
I was once working with spaCy, which is written in such a way that mutations to certain objects silently affect the whole module, so my unit tests inexplicably failed because they relied on things that happened in other tests not having happened.
Which is really annoying on their part.
Indeed, that's far from ideal. There's a pytest plugin that runs each test in a separate processes that can help in situations like that, fwiw
aw damn
Guys, is there any website which offers some sort of decent python challenges or questions to practice and improve skills?
Excluding paid options
here is a simple little game i made using python ```python
word = input("Select the secret word!")
guess_count = 0
while True:
guess = input("Guess the secret word! ")
if guess.lower() == word.lower():
print("You win!")
break
elif guess.lower() != word.lower():
print("You have guessed incorrectly try again!")
guess_count += 1
print("Your amount of guesses is " + str(guess_count))
if guess_count > 3:
print("You lose!")``` its a guessing game
its not much but its honest work
Rotund, if you win and break the loop you will never reach the elif, so you don't need to check if guess.lower() != word.lower()
But good job
@sullen widget while its under the if that code is needed
its to tell you if you lose or not and the amount of guesses you have used
You can use a for loop for that
Not the right channel, #βο½how-to-get-help
hey everyone i'm new here & also a little above than beginner. Is there any site or something where i can find a lot of realistic projects (not into web development) ? My main focus is on learning & gaining some knowledge please
Well i would suggest just reading code from github since there is a lot of Python code there
Maybe even read python source code for the standard libraries lol
Yeah, try solving stuff in a different way than what they did
Hey, I wanna know can I automate data entry with python
Hey, I wanna know can I automate data entry with python
@urban forum ofc you can
read selenium & requests module
Yeah, try solving stuff in a different way than what they did
@sullen widget ok gonna do that then
hi, I am trying to find the definition of a function from a package I downloaded
thing is, I used n++ to search all files for the name of the function, It just returns a couple of lines calling it, but no decleration/definition
there is a .pyc binary which has a string referencing it, I am guessing that is the definition, but it's been compiled ?
@finite girder This is not a help channel. It is intended for discussion of the Python language itself
ok
re is a standard library module, right?
Yup
Cheers :)
is there a way to hash a str without using a third party library? (Using Built in Library)
noice
i imagine it's not cryptographically secure, but you know, it'll do for your purposes probably?
hey guys, is this fizz buzz program correct?
number = 0
while number < 1000 :
number += 1
if number%2 != 0:
print(f"fizz {number}")
elif number % 2 == 0 :
print(f"buzz {number}")
oh never mind that just shows which numbers are even or odd
not the right channel, but fizzbuzz (is div by 3, is div by 5, and is div by 15) afaik?#βο½how-to-get-help
ight
Brunckek, there are collisions with the hash function but it is not that common, atleast not for strings
like with most hash functions π€·ββοΈ
Python provides hashlib if you need hashes that are unique, hashes of strings are random between processes and the hash func is more about hashing speed
I tried a = hash("A")output everytime I tried to run it was different
thats because that how it works
i get the same one everytime
in the same interpreter loop anyway
gueesing that's the way the interpreter loop is setup
starts by initializing the hashing functions in some way
its different between processes (hash() that is)
oh, he probably created a file and ran it everytime, heh
yea, in each process it will be different, that's how it's meant
which is why if you need to to be the same every time you want hashlib
Why is hash of two ints same?
for small ints, their hash is their value
(with inbuilt hash)
except for -1, that I never understood, is their a reason why hash(-1) returns -2
Yes but for some reason either hash(0) and hash(-1) or hash(-1) and hash(-2) are same
That's exactly what i meant
iirc there's no -1 hash because of an implementation detail on CPython
Something about it being used to represent failure states
ah i guess that makes sense, never thought of that just thought there was some weird bug
Same here. Doesn't it interfere with dict lookups?
don't think so because for 2 hashes to over ride each other they need to compare to equal with == and their hashes (hash()) need to be equal so values like 1, 1.0 and True collide, thats why you get ```py
{1: 1, 1.0: 1.0, True: True}
{1: True}```
you can also add 1+0j to that
Hashes for strings are randomised because of some vulnerabilities it exposed, otherwise it should always be the same (at least on that python version)
Hashes for strings are coherent (a == b => hash(a) == hash(b)), but the algorithm is randomized on each run. If it was the same every time, it would be possible to find a long sequence of strings that causes a hash collision every time (two consecutive strings have the same hash mod something), and it would be possible to exploit this behaviour to make filling a dict with n values take O(n^2) time.
I wonder if other languages deal with this
Wonder what JS does...
https://v8.dev/blog/hash-flooding found this link
how interesting
C# apparently does both a ref compare and a value compare, i had to double check that in the c# server tho π
In OCaml, you can choose whether to do that when you create a hashmap.
;; though
i mean i can understand it's a different mindset and all, also gotta get used to currying, but damn, functional languages are different
I just have a hard time finding practical use cases for currying
Like I more or less get how they work but I can't seem to find when I should be using them
When you use a function with the same first argument a lot of the time
(Doesn't have to be the first argument, that just makes it easier)
Sure sure, I just can't think of a situation where that's often the case. I'm sure I'll stumble across it
I have no idea what currying is, but the conversation makes me think of things like bigrams or pair wise combinations or so on
Where we have a generic n gram function for example, but we are usually setting n to 2 when calling this function.
Let me get on my computer and I'll look for an example
for example, you can compose operations on lists like hs op = unique . map (+ 1) . filter even
curry (botUpdates newSeq) <$> takeTMVar origState``` I don't know if that helps
Probably not :/
currying is basically from functools import partial right?
That's partial application. They're similar
currying essentially means that a functions takes a single argument and returns another function which takes the next argument, so
def add(a, b):
return a + b
```becomes
```py
def add(a):
def add(b):
return a + b
return add
how often do you guys find yourself using something like this, or other similiar function-paradigm ideas in your non-functional code
i've been forcing myself to pick up a functional language for too long
but, tbh, haven't really found a decent reason why
just a different paradigm, or is there something more?
This? Not very often
Map, filter, reduce, etc a lot though
can all be replaced via comprehensions though, even preffered if i recollect correctly
I do sometimes end up making essentially monadic error handlers
you cannot make reduce with a comprehension
List comprehensions are fine if you only have one thing to do, but when you start combining operations it becomes really messy
^ fair
I googled currying and now I'm more confused than before.
getAttribute :: Monad m => m a -> (a -> m b) -> m b
getAttribute attr attrParser = uncurry (>>=) (attr, attrParser)```
This I would probably never do outside of FP though
yea, the functional paradigm can be odd coming from oop or other conventional paradigms
at least the in depth stuff
uncurry (>>=) (attr, attrParser) why?. couldnt this just be getAttribute = (>>=)
I'm looking at my code right now trying to figure that out
, now i feel better being completely dumbfounded reading that
This was my first project ever. Man, it's embarassing looking at old code
that just means you're growing :p
I wish I could go back in time and kill the old me. What an idiot that guy was
Hey would people pay a webscraper money to scan for CISA alerts?
Is there anyone willing to help me through zoom please! Its basic python for most of you im sure
This is not a channel for asking for help with python, if you need help with python check #βο½how-to-get-help @velvet fossil
@loud summit π
this is related to the discussion at general, if you import a module inside a function, the module is tied to the function scope, yet sys.modules still includes it, but it's not available via reference in the global scope, does that mean it's imported just not available or something else?
Imported, but there's no name referencing the module object outside of the function (and sys.modules obviously)
sys.modules will hold all the imports you do since they're not shared across packages, if you don't import it whole that just means you don't have the name referencing it but the import mechanism is the same
import something
something = __import__('something')
these are essentially the same, not sure if that's how it works under the hood, but still
thus, importing inside a function does the exact same importing procedure, but assigns the module object to a local variable in that function/class
python is a beginer friendly language, but damn does it have a lot of magic underneath
It can be confusing, but its fairly consistent
yea, don't mean it's not
but, damn, i thought i was fairly versed in the language a few years ago
im still not π
Hi i have a class cup, and i want to make an inbuilt function that measures the volume of the cup, So i have a class Cup: And i want to find to get a value when i call Measure(Cup)
I'd say there isn't much magic, more hidden implementation details. Most things follow clearly established rules and don't work just because "uhh we needed that so we did some magic under the hood and there's no way for you to do the same"
by magic, i meant hidden implementation details
by no means a small language
but yea i get what you mean
is python IDLE bad?
what i dont really like bout idle is that its line by line execution
I mean... yes?
so if i mess up
That's Python
like with a text editor u can run all lines at once
when u tell it to run
like i dont like when ur running and editing at the same time
!unsilence
β unsilenced current channel.
Is there any solution to mypy not allowing covariant type variables in a parameter?
Something as simple as
def choose_from(a: T, b: T) -> T:
return random.choice([a, b])
is impossible
Doesn't make any sense to me
It may be something they have to tweak. Or possibly is addressed or needs to be addressed in an issue on their repo
What does covariant type variable mean in this case?
You can have restrictions put on your T.
In this case it means that all T should be the same
So it's a function that takes two values of the same type T and returns a value of type T
import random
from typing import TypeVar
T = TypeVar('T')
def choose_from(a: T, b: T) -> T:
return random.choice([a, b])
this works fine for me
Success: no issues found in 1 source file
T = TypeVar('T', covariant=True)
error: Cannot use a covariant type variable as a parameter
it kind of doesn't make sense
wouldn't a covariant parameter just accept Any? or do i misunderstand covariance
I found this https://github.com/python/mypy/issues/7049
covariance and contravariance is one of those topics that always seems easy until i try to apply it
i always need to approach these w/ pen and paper
hm, it works with non-member functions
Well, subtype typing rears its ugly head at us :)
yes, this works:
def bind(self: Maybe[T], f: Callable[[T], Maybe[U]]) -> Maybe[U]:
if self.is_nothing:
return Maybe.nothing()
else:
v = cast(T, self.value)
return f(v)
x = Maybe.just(5)
y = bind(x, lambda u: Maybe.just(str(u)))
reveal_type(y) # Maybe[str]
oh, wait
For some reason, this works:
def __ge__(self: Maybe[T], f: Callable[[T], Maybe[U]]) -> Maybe[U]:
if self.is_nothing:
return Maybe.nothing()
else:
v = cast(T, self.value)
return f(v)
Wow, this is almost magical.
x = Maybe.just(42)
y = x >= (lambda u: Maybe.just(u))
z = Maybe.just("str")
w = z >= (lambda u: Maybe.just(u))
It correctly deduced that y is Maybe[int] and w is Maybe[str]
No, I'm just experimenting with typing
wait
This method gives me an error!
def __rshift__(self: "Maybe[T]", right: "Maybe[U]") -> "Maybe[U]":
return self >= (lambda _: right)
I have no idea why >= works but >> doesn't.
But if I change U to a contravariant V, it works
i'm trying to use typing. my main aggravation is where a variable is Optional[str], and i use it where it's expecting str. None of the solutions to this seem nice to me.
If we had a switch case it'd go seamlessly
However it'd then still be banking on needing the types, so it wouldn't really work
@spark magnet i've used cast for that... very frustrating
yeah, cast is gross, assert is gross
it's very clever that mypy will attend to asserts, but i don't want to litter my code with asserts
we need that "none-aware" operators pep π
I kind of feel like..... Python is a dog and MyPy and typing is a silly costume that your weird girlfriend bought for it. The dog really doesn't like the costume. I mean it'll wear it and put up with it, but eventually it'll try to rip it to shreds
All the forced typing just doesn't mesh well with how Python is built
that said, it helps me more than it hurts me
the method/attribute completion that it enables in my IDE is more than enough for me to justify using it
making docstrings a lot more parsimonious
Sure, but if you eventually have to start re-writing your logic to accommodate it, that feels like a step in the wrong direction
mypy catching a whole class of errors
its not really logic as much as it's occasionally slapping cast in there
You just need to have an if before being able to use an Optional as if it was the type contained in it.
@full jay i was very skeptical of typing, but i like it more than i thought i would.
I'm not knocking type checking, not in the slightest
well under 1% of my LoC written is dedicated to making mypy happy
@spark magnet I mean I love statically typed languages. It just feels.... bizarre and out of place in Python
that's a worthy tradeoff for me considering that it's still a nascent technology
@zenith topaz sometimes the "if" is actually complicated logic that I know makes a guarantee, but mypy can't follow it.
That seems like its a bug in mypy.
I try type most stuff if i can but i dont go out of my way for mypy
the problem with any type system is that it has to either reduce the set of valid programs or be quite complex or be unsafe.
I just wonder if it'd be better to make it a superset of the language
Something more akin to TypeScript
There's several type checkers avaiable aswell, mypy isn't the only one.
Sure sure
But I feel we're restricted by the language itself at times
Eh, I'm likely just being fussy
@zenith topaz i won't call it a bug in mypy: the logic might be in another function some place.
If the logic guarantees something to be an X instead of an Optional[X] the typechecker should pick up on that.
@zenith topaz not across function calls
b: int = user_input_int()
a: Optional[str] = None
if b > 100:
a = 'string'
elif b < random.randint(101, 203):
a = 'another string'
```I would be very surprised if mypy picks up on sth like this.
seeing as this would require dependent typing to check
are UUIDs still buggy? im trying to generate IDs for objects and some cursory googling seems to say they are?
That's a problem because you are using > on an Optional[str] and an int
ah, my bad. Meant to put a different variable there
@narrow kettle i never heard that uuids are buggy
are they used in python to create IDs?
i just saw buggy in a couple SO posts i looked at
so i figured id ask
they are used in python programs. Python itself doesn't use them. what bugs?
I'm trying to get into type checkers. Is there a reason mypy is considered the "default" static type checker (at least, I'm getting that impression) when other well-developed ones like pytype exist?
no idea, SO just said "buggy"
@pearl river because mypy is written by the people authoring the typing peps
so i should be fine to use UUIDs then i take it π
(including Guido)
mypy was really the first major one, got help from dropbox (who really pushed type hints in python), ...
For me, pyright works as well
from typing import Optional
import random
b = 9
a: Optional[str] = None
if b > 100:
a = "string"
elif b < random.randint(101, 203):
a = "another string"
reveal_type(a)```
```py
note: Revealed type is 'Union[builtins.str, None]'```
Looks like mypy indeed didn't pick up on that one.
because mypy is written by the people authoring the typing peps
hmm, now that's a pretty decent reason
it would be kind of absurd to expect mypy to understand the semanticcs of randint
i'm trying to use typing. my main aggravation is where a variable is Optional[str], and i use it where it's expecting str. None of the solutions to this seem nice to me.
one solution would be
def process_optional(x: Optional[T], on_present: Callable[[T], U], on_missing: Callable[[], U]) -> U:
if x is None:
return on_missing()
else:
return on_present(x)
but you might have some external knowledge that x is not None
However, some might argue that this knowledge (how do you know that x isn't None) should be communicated explicitly.
yes, mypy isn't a proof assistant :)
sadly
yes, was just giving an example of why mypy cannot always determine that Optional[T] is just T
yes,
mypyisn't a proof assistant :)
yet
Even with just b < 100 it won't figure it out.
But with just an else it does.
Python isn't dependently typed (y e t)
@spark magnet is it? randint returns an int, isn't that all it needs to know?
@paper echo the example here was a comparison on the return value
it can't know that (b > 100) and (b < ...) are opposite
@grave jolt isnt there another one? pyre?
?
@grave jolt your example code seems wildly over-complicated for my needs π
from typing import Optional
import random
b = 9
a: Optional[str] = None
if b > 100:
a = "string"
else b < 100:
a = "another string"```
Pyright was able to figure this one out.
oh i see
where you wouldn't expect a type checker to know which branch to take
right... that's the general problem isn't it?
for that matter, how does something like haskell do this?
monads?
Which is neat since PyLance uses pyright for the autocompletions
meaning that every succeeding function that handles b in this example would have to be "none-aware"?
(enforced by the type system)
Haskell doesn't have the null-issue that mainstream languages have by making it explicit
haskell has really nice null handling and does allow partial functions
If you want a nullable type, you need to use Maybe a which has a special member Nothing, and you have to process the case of a missing value and a present value explicitly
but, as lakmatiol said, there is a partial function fromJust which will blow up if you pass Nothing in there
right thats what im saying. in a haskell program, every function that receives a b as per your python example would have to accept Maybe int and not just int
so in python you should write code that accepts Optional[int] to receive that b
languages like idris and agda can prove pretty much any invariant
and you'd have to cast by design and by analogy to other typed programming languages
right ive heard there are issues w/ dependent typing though
well, in haskell you generally do map someFunctionThatTakesInt maybeInt
right
yeah, I still live at my parents' house
right ive heard there are issues w/ dependent typing though
which python doesn't really have because python and haskell are entirely different languages
and haskell only has dependent typing if you enable GHC-specific extensions
dependent typing is not really mature enough to be used in practice afaik
T = TypeVar('T')
def pass_null(fn: Callable[[T], T]) -> Callable[[Optional[T]], Optional[T]]:
def wrapper(x: Optional[T]) -> Optional[T]:
if x is None:
return None
return fn(x)
return wrapper
@pass_null
def add_one(x: int) -> int
return x + 1
is this stupid or no
ah i knew i was reinventing some haskell thing
well, not haskell-specific
right
fmap is much more generic than this
well, fmap for an optional type
I would say it is not stupid tbh
same
good because ive used it a lot in my own code π
its realllly helpful for pandas especially
if you upgrade if x is None: to if x is None or math.isnan(x):
I can imagine. Python null and error handling really do need some work
Pandas handling needs work
Series.map has the under-used na_action='ignore' parameter
but DataFrame.applymap doesn't have it
nor does Series.apply
why 
@limber vigil check out #βο½how-to-get-help
This is not really a help channel.
@paper echo
pass_null :: (A -> B) -> Optional[A] -> Optional[B]
You can upgrade it to
can_fail :: (A -> Optional[B]) -> Optional[A] -> Optional[B]
And now you can chain together computations which can fail.
@can_fail
def sqrt(x: float) -> Optional[float]:
if x < 0:
return None
else:
return x ** 0.5
@can_fail
def inverse(x: float) -> Optional[float]:
if x == 0:
return None
else:
return 1 / x
@can_fail
def maybe_inverse_sqrt(x: float) -> Optional[float]:
return inverse(sqrt(x))
without using exceptions
in the end, it is all monads
monads all the way down
yeah sorry is this python or haskell?
nvm i think i missed some backstory
and ofc can_fail is a special case of wrap this function such that it accepts and returns a monad
where the monad can be.... anything
i cant wait to confuse my coworkers by using this concept for HTTP requests π
Alternative solution:
def sqrt(x: float) -> Optional[float]:
if x < 0:
return None
else:
return x ** 0.5
def inverse(x: float) -> Optional[float]:
if x == 0:
return None
else:
return 1 / x
def maybe_inverse_sqrt(x: float) -> Optional[float]:
return chain(chain(x, inverse), sqrt)
well, the type of can_fail is the same as monadic bind >>= in hs
well, when specialized for Maybe
you could combine both tbh