#internals-and-peps
1 messages · Page 89 of 1
In my specific use case it would simply make the API easier to use. def parse() and async def parse() both parse objects, but async def parse() can also parse coroutines.
It's not a problem that I'm depedent on and need to fix, but it was one of those things that I came across and got addicted to the problem
Well, it just doesn't work with Python semantics, in the same way that you can't create a decorator that works differently on an instance method and on a freestanding function; or on a normal function and a generator function
That's my assumption of it as well. You can bootleg a solution, but nothing viable from my research.
The main reason it's not possible is that x = func() on an async function is a totally reasonable thing to do. For example, in create_task(func()).
I'd say it's more like how you can't make a function that decides whether to return an int or a string depending on whether its caller wants an int or a string. It's both not possible in the data model, and not a sensible thing to do.
functools.singledispatch has a solution for different types (https://docs.python.org/3/library/functools.html#functools.singledispatch)
for taking different argument types, sure. Not for returning different types.
I agree it's not a sensible/logical thing to do, but confused on why it would not be possible?

class ReturnsX x a where
give :: a -> x
instance ReturnsX Int Int where
give i = i
instance ReturnsX (Int, Int) Int where
give i = (i, i)
x :: Int
x = give 42
y :: (Int, Int)
y = give 42
I have seen that (return type dispatch) actually used in some graphics library in Rust, I think piston
How would you make a Python function that works differently on
x: int = f()
and
y: str = f()
```?
Only viable solution from my knowledge of cpython is via inspect
But even then, inspect is not a module I take any pleasure in working with knowing it's not scalable
yep
def foo():
if caller_wants_int():
return int(some_var)
return str(some_var)
def caller1():
return foo() + 3
def caller2():
return foo() + "bar"
def caller3():
return foo() + foo()
Alright, let's imagine that you can figure out that caller1 wants an int, and return an int to it, and you can figure out that caller2 wants a str and return a str to it - by parsing the bytecode of your calling frame and seeing how the result is used, or whatever. What would you do for caller3?
and many times you don't have access to that information at runtime, unlike in some statically typed languages
like
def g(x: int):
...
def h(x: str):
...
g(f())
h(f())
My assumption was that you simply pass a flag to foo() dictating the return type beforehand. My hope was that await was similar to passing such flag, but the more I've researched, the more I've come to the realization it's not possible. The problem irks me for this reason, and while I don't research it, it would be lovely to find that it's actually possible
In other words, my hope was that await func() would set a flag on the call to func() that can be accessed on runtime
It's not just await. There are legitimate reasons to call a coroutine function to get a coroutine.
Like I said,
task = create_task(async_function())
i'm only half paying attention, but curio has a decorator that allows a function to be called as a coroutine or a normal function
if that's what you're after
Indeed! (that's what I was after / have my 👀 out for)
beazley is like the simpsons in that he probably has code for it already, whatever it is
Let me read through this source code. I have a solution, but it uses inspect.
Thank you for the share. Let me check it out
well, this uses inspect, of course
also
# curio/meta.py
# ___
# \./ DANGER: This module implements some experimental
# .--.O.--. metaprogramming techniques involving async/await.
# \/ \/ If you use it, you might die. No seriously.
#
it uses inspect to make sure signatures match
For my sanity I hope so, but logically, I hope it does not
if inspect.signature(syncfunc) != inspect.signature(asyncfunc):
raise TypeError(f'{syncfunc.__name__} and async {asyncfunc.__name__} have different signatures')
worse, it uses getframe for it https://github.com/dabeaz/curio/blob/b0f1a51187c57db67a0d5c1b6a28004a5743c72f/curio/meta.py#L57
i mean, that's a reasonable use case for inspect
Indeed it is. Another sad day
Although it doesn't do what you want @glad shoal, it checks if it's called in a coroutine context, i.e. inside an async def
So this should work, unlike checking if its result is immediately awaited
Indeed a better solution
Thank you for the share @deft pagoda
but still, it's a hack that is only guaranteed to work in CPython, and it's a very unexpected API tbh
it's not even "guaranteed" to work in CPython; it depends on implementation details
why are comments borderline invisible on mobile. I thought it was just a blank box
Haven't heard of this library, but something that might come handy in the future. Was planning on using asyncio.stream and asyncio.protocol for some networking purposes. Will be staring this to look into it further when I get the time.
i don't think the api is unexpected -- it's pretty well documented
It's unexpected as in: what else behaves like that?
I think it's quite unexpected to have a function change its behavior based on the context that it was called from, full stop
Currently working on a proxy management system/brokerage from scratch with SSL support (via MITM). Been having to break the problem further and further down, and now getting back into the networking. This library looks promising. Amazing share, thanks again.
i thought there was a function being released in a new version of python that detects context without the frame hack
I agree, but imagine the cool stuff one would be able to do. Your example above is a perfect example.
y: int = func()
x: str = func()
Well, that's possible in some statically typed languages when it's unambiguous
An interesting thought. It would allow some interesting use cases.
e.g. in Haskell there's a read function, which is like input, but it automatically converts the string to the given type (i.e. it's like the inverse or repr in Python)
Treat the entire file as a class, and you got a solution. ggwp (I kid, I don't even know if this is possible)
yes, that's a perfect example - what should happen if you do x = func() + func()?
That's undefined, I suppose. Just like x = func()
Indeed - that was the problem you raised earlier
unspecified
Undefined would be a good route, or function defaults to certain output.
yeah, I think all of that is terrible. 😄
def func() -> Default[int], Union[int, str]
(non working, ofc, but you guys get the point, hopefully)
i think that's the best part
but maybe x: int = func() + func() should work
btw, func() + func() works in Haskell
Incredible, yes, for sure.
...it just produces another function dispatching on the output type
A different set of paradigm to work with, but an interesting one nonetheless.
There are also very fun functions returning an arbitrary type, like error :: String -> a, but Python uses NoReturn for that
I'm afraid I've never looked into Haskell (despite folks saying it's a good language to learn for it's weirdness), so I can't comment on the photo, or the examples
Perhaps, however, (despite having no knowledge or ever having used it), MyPy might be able to fill this void.
Is it MyPy? I believe I might be thinking of something else.
My apologies if not.
!e
PROP = object()
class ContextMatters(type):
def __new__(meta, name, bases, methods):
ann = methods["__annotations__"]
for attr, val in methods.items():
if val is PROP:
methods[attr] = ann[attr]()
return super().__new__(meta, name, bases, methods)
class Test(metaclass=ContextMatters):
x: str = PROP
y: int = PROP
print(Test().x, Test().y)
@deft pagoda :white_check_mark: Your eval job has completed with return code 0.
0
i guess printing an empty string isn't fun
Another random thought, and another library I've not exhausted in my own use cases to know it enough. Can you modify runtime executions via the ast module?
maybe in combination with, like, ctypes? i'm guessing though
can compile some ast into byte code and replace something in memory
def func():
return hello
This builds on compile time. Can, then, one modify the runtime context of func() to give meaning to hello?
and therefore be able to create weird non-Python contexts?
i mean, once again, it's sort of a trivial thing to do in a class body
I would assume on file as well, with such example, via globals. But say the following:
def func():
return (15)2
Where (15)2 is equivalent to 15*2.
A random fleeting thought I've had in the past when minimally working with AST.
!e
from itertools import count
class IncrDict(dict):
def __init__(self):
self.counter = count()
def __missing__(self, key):
if key.startswith('__'):
raise KeyError(key)
self[key] = next(self.counter)
return self[key]
class EnumMetaclass(type):
def __prepare__(*args, **kwargs):
return IncrDict()
class Enum(metaclass=EnumMetaclass):
...
class Fruit(Enum):
APPLE
BANANA
KIWI
print(Fruit.APPLE, Fruit.BANANA, Fruit.KIWI)
@deft pagoda :white_check_mark: Your eval job has completed with return code 0.
0 1 2
i'd like python a lot less if it didn't have all this weird magic in it
My love affair only started a few months ago when I began diving deeper into its core
I understand your sentiment
Nowhere near as proficient
But, regardless of your knowledge, the real question still is: can you solve a Leetcode problem in 30 minutes with 3 interviewers talking to you at the same time?
definite maybe
!e Note that (15)2 is not valid Python syntax, so ast can't help you with that. This gives an exception without the function ever being run:
def f():
(15)2
@raven ridge :x: Your eval job has completed with return code 1.
001 | File "<string>", line 2
002 | (15)2
003 | ^
004 | SyntaxError: invalid syntax
I mean, you could certainly build your own parser that could make that work, but you can't use Python's, because it can only parse stuff that's valid Python code
I once used that with some esoteric hackery to almost completely break my shell (it still works, just requires some esoteric hackery)
I forgot what exactly I did but I can probably find it
ohh, how did it almost break your shell
the thing with what i was doing is that [] still works
import sys
sys.meta_path.clear()
sys.modules.clear()
@mint forge
So not quite that but the same effect
Every time you run a valid python statement it tells you that it's lost the builtins module
lol
I don't think that actually clears sys.modules though
Oh wait it does but it breaks at that point
very cool
Anyway yeah the shell is basically unusable except that running print() still works
I suppose if I combine this with del builtins.xxx that could totally destroy it
do it
import builtins
_del = delattr
for i in dir(builtins):
_del(builtins,i)
del _del
import sys
sys.meta_path.clear()
sys.modules.clear()
Oh bugger I delete delattr lol
Oops I just killed my shell because I forgot I already killed python
oh crap I broke xonsh
Ctrl-D?
i closed the cmd
module not iterable
Haha
Really? What version?
Can’t exit
3.8.5
It 'works' in py380
Trapped for eternity
Weird
Wait not my py38 is 385
The heck
Oh wait I deleted __import__ too so the sys hack doesn't work lol
This esoteric code is becoming esoteric
yep but it is cool ngl
import builtins
_del = delattr
_imp = __import__
for i in dir(builtins):
_del(builtins,i)
del _del
sys = _imp('sys')
sys.meta_path.clear()
sys.modules.clear()
del _imp
del sys
should work
I think deleting globals breaks everything
in ipython it just exists out
LOL probably because I literally broke 99% of the repl
ImportError: __import__ not found
🤔
that still gives me module not found
CPython?
ah ok
You should be able to just paste my message
Note that for some reason it doesn't think _imp is defined - I think it's because I'm deleting globals
this is the error i get lol
Yup
You should be able to del _imp and del sys now to completely destroy any chance of doing anything in that shell
it's already deleted
Well that's not true though
If anyone finds a way out of this I'll be very surprised
There's no way of giving any output
I've deleted both open and print, as well as __import__
It is possible to recover from that
There should literally be no way out that isn't more esoteric than the way we got here
oooooo, more estroic code?
You can traverse the subclasses of object to get an importer that works
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'object' is not defined
haha
...
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: __build_class__ not found
().__class__.__base__
lost builtins module
Works if you assign it to a
The lost builtins module just means you can't repl-print
right, so how to go about recovering after doing that
Not sure where to go and we can't dir in this shell. Time to walk blindly :D
I think I broke the autocomplete lol
@livid geyser you can do dir = lambda o:o.__dir__()
or you can do type = ().__class__.__class__ then dir = lambda o:type(o).__dir__(o)
once we get back open we can print
break python then rebuild it, wow
@clear kindle See #❓|how-to-get-help, this is a dicussions channel
My bad, sorry
I don't see any of ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] helping us here
This really is an esoteric escape lol isn't it
yes
Perhaps we should move to #esoteric-python lol
take me with you
you need to think creatively to recover a shell from this point
has there been a PEP to deprecate string literal concatenation, like "a" "b" --> "ab"
or a mailing list thread at least
Why would they?
Mostly a useful thing from my experience
Same, with multiline strings
Also, this would break way too much code
in my experience it's just a source of bugs
i don't know any cases where i would write "a" "b" or ```python
"a"
"b"
and where i couldn't just write `"a" + "b"` or ```python
"a" +
"b"
instead
i know a lot of code uses it
but that doesnt mean its a good feature
it makes sense in C where the whole idea of concatenating strings isnt easy due to memory allocation
The first one will error out in most cases though
I've been using it with \ tbh
"a" \
"b"
Isnt this proper usage?
Or is it /, can never remember
It's \, but you should mostly use the implicit line continuation in parentheses instead of that
yeah you would need line continuation outside of parentheses
this is used often in Scikit-learn source for example when formatting error messages
raise FooError("This is the error message "
"that is shown to the user.")
raise FooError("This is the error message " +
"that is shown to the user.")
but really would this be so bad?
I find the concat a big ugly, while it can be confusing at times when you forget it, the benefit of being able to split strings where you want to fit into your col limit is much better imo
meanwhile if you meant to write
raise FooError("This is the first arg",
"and the second arg")
but accidentally deleted the , you get weird output and maybe not an error
the trailing + is that bad?
IMO yes, comma looks better
comma looks better? They do different things
The comma is separating the two strings into two arguments
To be printed tho, no?
FooError(*args)
Thats what i was thinking anyway
Idk why my mind immediately went to print
they do different things
In [32]: raise IndexError("a","b")
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-32-0ede76577b9c> in <module>
----> 1 raise IndexError("a","b")
IndexError: ('a', 'b')
In [33]: raise IndexError("ab")
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-33-03f3d98fed63> in <module>
----> 1 raise IndexError("ab")
IndexError: ab
Ah, print
Hmm okay, nevermind, i misread that, dunno why i thought of print tbh
But still if they did the same thing comma looks better lmao
yeah that's not the point im making
the point is that concatenation of string literals doesn't really benefit anyone and creates a new category of bugs that sometimes can be hard to identify
Being able to split a string on many lines without operators is very useful though
i guess, i just dont see the ability to omit + as something particularly important
can someone help me in this please
when I run the code shows me like this
thats not what happens when you run the code
thats linter warnings telling you your code style isn't the best
are you using tabs?
no
are you just pressing space 3 times
so what I should to do now
is that pycharm?
look for something like this in the bottom right
then reindent file with spaces, i think
also, this isn't on topic for this channel
but, there should be a button to fix your indenting somewhere
Also if what your trying to do is have 2, put \n between the text you want to seperate into lines
AFAIU the advantage of implicit string concatenation is that it's done at compile time, not runtime. Explicit concatenation with + would need to be done at runtime, and cost some performance.
as long as it's not very long, the concat will also be done at compile time
In [2]: dis.dis("'string' + 'anotherstring'")
1 0 LOAD_CONST 0 ('stringanotherstring')
2 RETURN_VALUE
Mm, fair enough. How long is "very long"?
People usually don't do this until they're over a line length limit, so 60 characters or so for the first string literal
that is a good point
longer than what any source code can reasonably contain
not what this channel is for
I want to dynamically define a class with a custom meta, how do I do that?
Like you can do type('Name', (object,),{}) but if I want to have a specific metaclass how do I do that?
Also if i wanted to pass the kwargs to __init_subclass__?
if you want to dynamically choose a metaclass i think you need to replace type with the metaclass of choice, i'm not sure about the __init_subclass__ part though
Apparently it's types.new_class
thats probably the intended way but looks like my suggestion may also work ```py
class Meta(type):
def new(mcs, name, bases, cls_dict: dict):
dict_ = dict(zip(cls_dict.values(), count()))
return type.new(mcs, name, bases, dict_)
x = Meta("MyClass", (), {1: "foo", 2: "bar", 3: "baz"})
x.foo
0
x.bar
1```
How do you guys define complicated app structure which has its own data to be represented into the interface?
Do you guys hold single data as an object in the program or something then representing it into the UI?
I'm just asking opinion, to see if there's useful explanation or designing methods i can get.
Hey @lilac mason, this question would better be suited to an help channel, see #❓|how-to-get-help
would a snake game work on discord using reactions for controls?
yeah i thought so
i'd seen someone do it in the discord.py server though
and yes, the lag was definitely there
didn't turn out as bad as i'd have though (off-topic for here i realize)
Is it true you still need to inherit from object to utilize __slots__?
I can't find anything about it under the data model but a rather well voted SO says it has to
I don't think you can not inherit from object in Py3
Oh, I suppose that makes more sense
If no parents are specified, object is implicitly filled in
But if I am inheriting from a class with a custom meta?
object would still be there in the inheritance hierarchy
About to start slotting all my classes bc why not if I dont need dynamic attributes?
Because it's premature optimization, and will surprise users of your classes
Yeah I decided not to
In my current project I decided to limit to cases where the property I have on the class access some class attribute, which I think is appropriate
Which was 2 classes
what is regex used for in python, i know you can find patterns of text like a phone number like 000-000-0000 but anything else?
Pattern matching text is very useful.
For example how @fallen slate's eval command sees a code block
The bot can read any message in the server, just like a regular user can. And any comment that starts with an eval command, it parses out the code block and runs it in a secure container.
This is a discussion channel though. Maybe ask about the bot in #community-meta
Yeah I was saying that @fallen slate uses regex to find the code block if there is any, I wasn't asking how python eval command works.
not sure if this is the correct place for this but can someone explain this behavior:
!e
foo = 'outer'
class Test:
foo = 'inner'
bar = foo.upper()
baz = [foo.upper() for _ in range(2)]
print(Test.bar)
print(Test.baz)
You are not allowed to use that command here. Please use the #bot-commands channel instead.
well it prints
001 | INNER
002 | ['OUTER', 'OUTER']
I have no idea why the list comp uses the scope outside the class
that's very odd
the inner scope isn't even visible to the comprehension...?
!e
class Test:
foo = 'inner'
baz = [foo.upper() for _ in range(2)]
print(Test.baz)
@gleaming rover :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 3, in Test
004 | File "<string>", line 3, in <listcomp>
005 | NameError: name 'foo' is not defined
whattt
ok that's a lot weirder that I thought
Listcomps are implemented partially atop functions, and just like methods don't see class scope, neither do they. It is somewhat unexpected though
yeah
!e
import dis
def f():
return [x*x for x in y]
dis.dis(f)
4 0 LOAD_CONST 1 (<code object <listcomp> at 0x7f3cfedd27c0, file "<string>", line 4>)
2 LOAD_CONST 2 ('f.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (y)
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x7f3cfedd27c0, file "<string>", line 4>:
4 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 12 (to 18)
6 STORE_FAST 1 (x)
8 LOAD_FAST 1 (x)
10 LOAD_FAST 1 (x)
12 BINARY_MULTIPLY
14 LIST_APPEND 2
16 JUMP_ABSOLUTE 4
>> 18 RETURN_VALUE
It's sort of like
def f():
def _listcomp(.0):
rv = []
for x in .0:
rv.append(x * x)
return rv
return _listcomp(y)
Hi everyone
I am trying to put together a simple app together as a project that I have to deliver as I am studying.
#my knowledge with python is very little still. I am having issues with an error related to json when I try to test it using postman
If I share with you guys my issues would anyone please give me some help ?
Hey @ivory gorge this channel is regarding python discussions, check out #❓|how-to-get-help
What is the reason for the lines in the disassembly of that code above is only made from even numbers/factors of 2?
each instruction takes up 2 bytes
Oh okay
so that's the relative address of each instruction
👍 thanks for clearing that up
Anyone here got tips for creating an extension system for existing projects?
Looking for something that specifically allows me to extend a singledispatch classmethod function. In other words:
Project:
class Foo:
@singledispatchmethod
@classmethod
def bar(cls, msg: str):
print("str", msg)
Plugin:
pip install plugin
def bar(cls, msg: int):
print("int", msg)
Foo.bar.register(bar)
Does not need to use singledispatch, but the idea is to use create a secondary function with a different type, registered by this plugin via pip install. The idea of loading the plugin via Project is trivial, but registering the function is my issue.
There's singledispatchmethod which ignores the first argument IIRC
I'd assume it would work for classmethod as well
Yes, so sorry, meant to write singledispatchmethod.
Anyone have a book recommendation on useful patterns written in python
Fluent Python
quite quite
hi i have a hard time knowing when to use method and when to use functions
is there a rule of thumb of when to use which?
method is asociated with an object (class)
method is a function, it just belongs to and object
the only real difference that with method, the object will be passed to it as an argument
(that's the self)
hm ok for instance if a have multiple objects(class) with different int(values), and i want the program to return the highest value. And with that I use a for loop, do i use the for loop within method or function?
if a function only takes those ints as parameters, it's just a function, it's only a method if you were to actually extend the int class itself and use it there
i.e.:
This would be a method (in this case a static one, because we aren't taking self) ```py
class extended_int(int):
@staticmethod
def max_from_sequence(*ints):
...
This would just be a fuction```py
def max_number(*ints):
...
it's not a mistake if you called method a function, because it is a function, but you can't call any function a method, only those that belong to certain objects
ok thx!
The rule of thumb is that everything is a function, and function bound to a class are methods
That's almost right
When you create a function inside of a class definition, you will "just" create a regular function, because that's what the statement does, but because you're doing that in the definition of a class, you assign a class attribute to the function instead of a regular name.
When you then access that function as an attribute on an instance, you'll get a bound method, as functions are descriptors
They have a __get__ method and that takes care of binding the instance to the function to create that "bound method"
!e
class MyClass:
def my_function(self):
print("hello!")
print("Regular function object:", MyClass.my_function)
my_instance = MyClass()
print("Accessing the attribute through an instance gets you a bound method:", my_instance.my_function)
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
001 | Regular function object: <function MyClass.my_function at 0x7f840e9c6940>
002 | Accessing the attribute through an instance gets you a bound method: <bound method MyClass.my_function of <__main__.MyClass object at 0x7f840e9d3f10>>
is isinstance(instance, Type) equivalent to Type in type(instance).mro()?
I'm running across the following issues: some clients want to run a python script with syncs local changes in an excel sheet with an API. The client is non-technical, so they dont really understand a CLI. I'm thinking about creating either a scheduled task using win 10 scheduler (and letting the IT guy set it up) which runs the python script every X hours, or creating an exectutable python file which will be idiot proof. Curious to hear opinions about one or the other, or another possibility.
Is using something like pyinstaller even best practice?
There's a bunch more checks involved, including things like __issubclass__ hooks
yeah
for example, you can have isinstance(x, T) for types from collections.abc, even though they have no direct instances
!e
from collections.abc import Sequence
print(isinstance([1, 2, 3], Sequence))
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
True
how does one find out what was used in order for something to be done? for example, with a string comp such as s = '', if s ... then s will be False because it's empty, but I don't understand what was used for this to be done. Looking at dir(s) isn't clear either, I expected somethign along the lines of __bool__ in there, but didn't see it
i tried dis.dis(s == True), but this throws TypeError: don't know how to disassemble bool objects, so I'm not sure how to find out what it is which enables s = '' to be evaluated as false
the key is to recognize that if is the statement doing the actual invocation/work, and so s may not necessarily expose the mechanism itself
oh, anything with __len__ will eval to False if len ==0 🤔
it's not clear how i'd find out what the if is doing under the hood, dis is (presumably) not the right approach
or is it just something that you know / search for in a doc / or don't know
not always. statements are usually the annoying ones. this is where googlefu helps a lot
Once you know where to look, then you can begin.
yeah i was coming up short there 😦
Hi I just joined this server, do you guys have any suggestions of which programming app I should use?
I have recently started learning Javascript
@unkempt rock read the topic
I did
you're in the wrong channel then aren't you
sorry
for example, in checks for membership, but you may not necessarily see which mechanism it defaults to by just inspecting the objects themselves. Although it can help at times, since python is pretty good with names for its dunders
This might have been said as I'm 50 messages late. If an object does not implement __bool__ then the fall back is the return of __len__. Any nonzero integer evaluates to True. If neither __bool__ nor __len__ are implemented then the result is True.
Cheers, that's from the documentation linked above too, is there any heuristic / approach to finding that out from inspecting an object tho?
Maybe it's just a case of reading the docs 😅
Yeah lol
You could look at the object dict and see if both bool and Len are implemented
Hi there. Thinking about * usage in function parameters. I noticed that devs use it to enforce argument names. I cannot find official feature discussion. And wondering if this is the right usage for it, since it does not look like a Pythonic way of doing stuff. To me it looks like a hack
def foobar(foo, * bar):
print(foo, bar)
foobar('foo_var', bar='bar_var')
!pep 3102
Any reason you think it looks like a hack?
thanks @unkempt rock !
@peak spoke It's an implicit way of restricting user from passing keyword arguments into the function without providing names for them
How is it implicit? You have to use the specific syntax and will get a clear error if you try to use the function's interface improperly. Being able to specify kwarg only args (and positional only) is important to keep the code readable from the caller's side, and it must have the split if you use varargs
Isn't keeping the code readable not the responsibility of the caller's side?
let's address the two separate questions separately. First, it's explicit. Implicit would mean there's no clear indication and/or the default approach without extra syntax would behave this way. But we know that the default behaviour allows both keyword and positional args
Second, keeping code readable is definitely the responsibility of everyone who writes code, both callers and the library makers.
Keeping their code readable is their responsibility, and having to specify it with a name is much clearer than just passing in True for example. It also helps keep the API stable between versions as moving around positionals changes behaviour but kwargs don't care about that
It's the same reason why python has some really idiomatic syntax. If the language makers decided that the responsibility was solely on the code writers, it wouldnt be necessary to incorporate some of the very things that make python great now.
So, enabling good code is a noble pursuit, and people who create code for the sake of consumption should keep it in mind
I think boolean flags are a great example for this specific feature. if i have a param that takes 3 boolean flag with some default values, it will be very confusing and potentially error-prone trying to rely on just positional args for them
keyword args are also great for when the API is still under flux, and more params may be introduced down the line
Forcing args to be keyword only allows the API makers to have the freedom to add args in an order that perhaps looks logical or makes sense
without breaking the existing code bases
thank you for sharing your knowledge @visual shadow @peak spoke . I understand it now
anytime!
ofc keeping the code clean is their responsibility especially for api, for example if wanna implement it with sdk which it is neccessary to keep "clearer"
anyone know if you can access **kwargs without looping trough them, like kwargs.key?
if you have **kwargs or any other parameter with the two stars in front of it, that parameter gets passed into your function as a dictionary. It is a regular dictionary.
!e
def thingy(**mabob):
print(mabob)
thingy(a=1, b=2, c=3)
@boreal umbra :white_check_mark: Your eval job has completed with return code 0.
{'a': 1, 'b': 2, 'c': 3}
calling it kwargs is just a convention; the ** operator is what imbues it with these magical properties.
thanks for that, mate
No problem. I think I have a few more minutes if you have another question about that.
Nah, i reached my intended result for now
Today in "surely it wouldn't"
Damnit variables, why can't you just magically scope yourselves
I have no clue why n_op is becoming a global variable here, even without my n_op = "booyah" it's a global. 😓
@quick glade for doesn't have scope in Python
It's more convention and good practice to not refer to whatever variables were created within them
Another thing, lambdas and functions are late-binding; when you build one that contains a reference to some closure variable, it won't actually store the "current value" of said thing, just the name of what it should refer to
Yeah I know about the for scope, that's why my booya worked.
My issue was that the lambda would always take the last value of what n_op was in the loop.
I assumed lambda worked like inner functions (for decoarators) in the way it treat variables from outside itself
You could use a function factory for that fwiw
damnit 🤦♂️
What's a function factory?
Something like this enforces _ to be bound to whatever that was passed
def eager_bind(n_op):
def _(self, other):
return N(self, other, n_op)
return _
Oh ok that makes alot of sense
Hi I was wondering how I could compile python for my os?
Like compile to a bin that my cpp kernel could use
what do you mean by "cpp kernel"?
no
all the major ones, AFAIK.
In any event http://nuitka.net/ is the closest thing to what you're asking for that I can think of.
pyinstaller?
well, depends what you mean by "compile" and "bin"
im assuming bin == executable
nuitka produces native self-contained executables, PyInstaller doesn't - but PyInstaller is also a useful direction to check into.
nvm found this https://wiki.osdev.org/Porting_Python
"This article is a bit out of date, poll User:Sortie or check his patch to Python 3.4."
and thats for cross compiling python
oh, wait - you're trying to compile the interpreter, not a Python script?
yea lol
arent there build instructions on the github
since these are really outdated
wish osdev had documentaion like this, we got literately 100 pages of real documentation and the rest is a 2700 page manual written in asm lmao
https://devguide.python.org/setup/#compile-and-build also - but that may not be geared towards cross-compiling.
do you even need to cross compile though
aren't you trying to run on your own computer
depends on what the computer is - if it's running a handmade OS it may not have had a compiler ported to it yet, or it may be running on hardware slow enough that compile times are unreasonable
but yeah, if autotools and make and gcc are working on it, then just build as normal instead of cross compiling.
is anyone here familar with Binary search trees/AVL trees?
Please keep rickrolls and similar in off-topic, this channel is strictly for Python related talks
!e
print(1 + not 0)
@grave jolt :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | print(1 + not 0)
003 | ^
004 | SyntaxError: invalid syntax
Why is this invalid syntax?
I think it's because + has a higher binding precedence than not
So, 1 + (not 0) would work
You can experiment with it by turning it around and observing the result of not 1 + 0 vs (not 1) + 0
Both will work, but you'll get a different answer
Let's check the grammar
Yeah, not_test is above arithm_exp
And a construct can only be made of constructs below it
Right, but it doesn't mean that it should be invalid
!e
def f():
print(x + - y)
print(x + ~ y)
@grave jolt :warning: Your eval job has completed with return code 0.
[No output]
@grave jolt That's not equivalent, those unary versions have a higher binding precedence than the binary + while not has a lower binding precedence than +
Why should precedence matter when deciding whether something is valid syntax?
So, x + - y will be equivalent to x + (-y)
Because it's now tried as (1 + not) 2
as far as I understand it
!e
print(x + - y)
print(x + ~ y)```
You are not allowed to use that command here. Please use the #bot-commands channel instead.
!e
print(2**~5)
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
0.015625
Hmm, right
That's because of this footnote:
The power operator
**binds less tightly than an arithmetic or bitwise unary operator on its right, that is,2**-1is 0.
I think @true ridge may know the proper answer here. I'm just guessing it.
Because that’s how operator precendence work with LL(1) syntax
doesn't python 3.10 use a new parser?
I don’t think the syntax have been updated so deeply yet
Actually the precedence of not is a different than rest of the unary operations (see the precedence table on the docs)
after + you expect to see any expression with either higher precedence or with parenthesis
It is not actually relevant with LL(1) directly
In case of anyone interested more deeply, I suggest checking out the precedence handling code at ast.unparse. It used to parenthesize every expression, but now it calculates and tries to actually imitate a reverse effect of what the parser does in terms of precedence (also for **, see the right/left associativity stuff): https://github.com/python/cpython/blob/3bd6035b6baf1a7d51b7cc2c6bb2c81886236b67/Lib/ast.py#L1360-L1375
Interesting, thanks for the correction!
Hello @unkempt rock, this isn't the right channel to share your blog posts, please use #python-discussion for that
All good :+1:
from collections import defaultdict
while True:
#Let the game start
game = input('Do you want to play the game? Say Yes/No')
if game.lower() == 'no':
break
elif game.lower() == 'yes':
# a dictionary to store the data
store = defaultdict(list)
love = list(map(str,input('What do you love ?').split()))
store['love'].extend(love)
good = list(map(str,input('What are you good at ?').split()))
store['good'].extend(good)
world = list(map(str,input('What the world needs ?').split()))
store['world'].extend(world)
money = list(map(str,input('What you can be paid for ?').split()))
store['money'].extend(money)
now after storing the data in the dictionary we will compute the values for the given variable i.e. vocation,world etc.
#intersection of world and money for vocation
for ch in store['world']:
if ch in store['money']:
store['vocation'].append(ch)
#intersection of money and good for profession
for ch in store['good']:
if ch in store['money']:
store['profession'].append(ch)
#intersection of good and love for passion
for ch in store['good']:
if ch in store['love']:
store['passion'].append(ch)
#intersection of love and world
for ch in store['world']:
if ch in store['love']:
store['misson'].append(ch)
for ch in store['good']:
if ch in store['love'] and ch in store['world'] and ch in store['money']:
store['lkigai'].append(ch)
for a,b in store.items():
print(a,b)
the ** break** is out of loop
line 7
idk why or how
This channel is for discussions about the Python language itself. See #❓|how-to-get-help if you want to get help with your question.
that's not advanced
cant find those help channels
can you help?
If #❓|how-to-get-help is not clear:
you should go to one of the channels in the "available help channels" category and type your question.
alright no problem i realize that was... a little off topic
All good
:)
Hey
Hello. This is not a help channel. This channel is for discussion about the language itself. If you want help, please look at #❓|how-to-get-help
been trying to get into python an advice for getting started?
!resources
The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.
@magic hollow take a look here
thanks!
Question about Spark...
I have the impression that spark is widely use and it’s fast
Today I took the spark course, and learn it’s build on RDD blocks, where RDD is much slower than data frame
————————————
Then it come across my mind... is spark really helps us to process the data faster?
Yes, the data separate into partitions, and able to cache them definitely helps the speed.
However, with so many modules optimize dataframe, is spark really needed?
Please help me understand it 🙂
@austere gate this is a channel for discussion of the Python language. you can try #data-science-and-ml.
Got it. Sorry that I don’t know where to put up this question 🙈
you must be doing something special in your class
I think without overriding __eq__, it will only return true if it's the same instance
there are several things which could be happening here, for example, your Player class might be inheriting from something which does have __eq__, or the class itself might be a singleton (I doubt this, but it would be a case in which this would happen)
it doesn't
__str__ doesn't affect equality checks in any way
if i have a mypackage/lists.py and i want to import from a package called lists how do i do that?
when i do from lists.services import ListService pycharm complains
You are not allowed to use that command here. Please use the #bot-commands channel instead.
hi 👍
@unkempt rock This channel is strictly for discussion.
yo guys i just upgraded from python 3.7 to 3.8.2 but when i type python --version it still show 3.7
is it illegal to ask for help with YAML in this server
it's not illegal, but you might not get an answer, this is certainly not the channel for it though, this is for discussions about python itself
thanks
Try to add an environment variable with path of where you installed python
I think you need to specify python3. Or add the env path for where your python bin file is.
chill guys i figured it
Is there a way to apply @staticmethod decorator to every method in my class?
@radiant scroll there indeed is, but I would suggest making a module instead.
The thing is that this is already in it's own module, but that module contains 3 classes like these and I'm not sure how I feel about splitting this into another 3 files
I would lean more towards 3 files than 3 namespace classes. Since you can for example do a from import from a module
that doesn't work nicely with functions
I was hoping there was some class decorator that could automatically turn the methods into static ones
perhaps metaclass, but that seems like too much
you can easily make one, but consider how confusing it would be for users
and your editor
which cannot tell that such a decorator exists
If you're using mypy, you could probably make some sort of custom plugin, but that seems like overengineering
so I should split it into 3 modules, even if they'll only contain about 3-5 functions each?
yes
or consider whether you actually can't just have all the 15 functions in a single module without a separate namespace
they should be separated, but I suppose I can turn them into modules then, I wanted to use classes because it felt cleaner for the file structure, but if it brings so many problems with it, I suppose modules will be better
def methods_static_by_default(cls):
for a, v in vars(cls).items():
if not a.startswith('__') and callable(v):
setattr(cls, a, staticmethod(v))
return cls
``` should probably work as the decorator, though I didn't test it extensively. But yeah, modules are just much nicer for namespaces, since imports are designed to work with them.
Or you can just not mark the functions as static methods
!e
class Foo:
def __init__(self):
raise NotImplementedError
def bar(x, y):
return x + y
print(Foo.bar(3, 7))
if you really want to use classes
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
10
but it's unexpected as well
that would probably cause even more issues with the editor, yeah, I 'll just use modules
You could just put a # type: ignore or # noqa next to these methods
but yes, just use modules
I was wondering if there is some sort of protection for pypi.
If not, a malicous user could create a script that commits dozens of useless packages and pollute the namespace or not?
There isn't. In fact, it has been an issue in the past, especially with people claiming package names that are common misspellings.
But if reported, they do get taken down.
Sorry, quick question. This was in somebody's __setitem__: return self.value := self.value[:key] + value + self.value[key+1:]
Would this create an entirely new object every time it's run, or would an existing object just be updated?
hmm, I am thinking on how to fix that.
1 think is ppl who want to watch the world burn just commiting empty packages, another one is blackhats disguise a package and its functions with crypto trojans or something like that.
Guess that is the double edged sword of giving every1 the option for commiting.
For a package index of its size, it is not feasible for any sort of manual review of all submissions and all subsequent updates. Static analysis is not always reliable either. Ultimately, its the users' responsibility to make sure what they are downloading is safe.
Even if it were to be restricted to "trusted" submitters, that doesn't absolve the user of their responsibility.
sure, like always. static analysis is a cat and mice game between malicious programmers and the ones fighting them
not very knowledgable in linux, but apt package list works similar to pypi right?
I believe they're restricted to certain users e.g. the maintainers of the linux distro
There are usually companion package lists that are more public e.g. AUR
I found a weird usage of assigning a lambda to a variable: when you want to specify that a function satisfies a specific protocol or type alias:
Easing = Callable[[float], float]
back_and_forth: Easing = lambda t: 1 - 2 * abs(0.5 - t)
class Trajectory(Protocol):
"""
A trajectory is a way of interpolating between two points
"""
def __call__(
self,
x1: float, y1: float,
x2: float, y2: float,
t: float
) -> tuple[float, float]:
...
linear_trajectory: Trajectory = \
lambda x1, y1, x2, y2, t: (
x1 * (1 - t) + x2 * t,
y1 * (1 - t) + y2 * t,
)
is this too cursed?
AFAIK there isn't really a way to express it differently. Or is there?

back_and_forth: Easing
def back_and_forth(t):
return 1 - 2 * abs(0.5 - t)
or does the type checker not like that
nah, "Declaration "back_and_forth" is obscured by a declaration of the same name"
what I assume does work is
def __fun(t: float) -> float:
return ...
back_and_forth: Easing = __fun
``` but that isn't all that great
def this_is_an_easing(e: Easing) -> Easing:
return e
@this_is_an_easing
def back_and_forth(t):
return 1 - 2 * abs(0.5 - t)
this works (back_and_forth is inferred to be Easing) ^
but it's kind of strange as well
one benefit of using lambdas with Pyright is that the types of arguments are inferred bidirectionally
(i.e. here t is inferred to be float because of Easing)
sometimes it feels like gradual typing is just like another language nailed on top of Python 🤔
and it's like a wild animal
rest of Python: more or less uniform tools, one way to do stuff, very little undefined behaviour (in non-cursed code)
typing: multiple competing and incompatible tools; no standard way to extend or provide custom rules for stuff like dataclasses or attrs or
SQLAlchemy; as a result, many valid programs are not passing the typechecker
How do I add an instance variable a slotted class? This is essentially a monkey patch. Is there really no way around this?
@swift imp you could create a descriptor that stores the attribute in some external place
since __slots__ doesn't stop class variables from appearing, nor does it stop the descriptor protocol
Like
instance_refs = {}
class Descriptor:
def __get__(self, instance, attr):
return instance_refs[instance]
def __set__(self, instance, value):
instance_refs[instance] = val
like above?
Pretty much, though it would make sense to store a dict on the descriptor instance instead of making it global
True
another note, I would suggest making id(instance) the key instead of just the instance itself so that it works on instances with different hashing algos/which are unshable
True
Ok
Know what kills me, I'm trying to use weakref and the objects I'm storing cannot have weakrefs created
Probably bc theyre slotted?
Fuck it
Can always add weakref to slots
At that point I might as well just subclass and replace it in the module no?
Unless it becomes an issue I'll just forget about the weakrefs for now
Adding to slots after the class is defined doesn't do anything. That was my first attempt
can anyone help me diagnose why this isn't working the way I expect it to?
I'm trying to cross reference data in a pickle from an hour ago and only print new listings but for some reason I'm getting dupes every time I run my scan.
@hasty lily This is strictly a discussion channel. See #❓|how-to-get-help
What do you mean?
!shhh
✅ silenced current channel for 6 minute(s).
Again.
!warn 791101296576823367 I'm not sure if you're making it deliberate, but please refrain from continuous off-topic discussion in a channel after you've been told by staff to move to another one.
:incoming_envelope: :ok_hand: applied warning to @unkempt rock.
!unsilence
✅ unsilenced current channel.
Hey @unkempt rock!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
Good morning sun_with_face ll Good evening
Can I use Google maps API to get directions to a certain location...? If yes, mind giving some insights..?
why is StopIteration an Exception subclass when GeneratorExit is only a BaseException subclass?
they both aren't technically "errors", so is it just legacy reasons?
Sadly I don't see any information on why it's a Standard Exception and not a BaseException, https://www.python.org/dev/peps/pep-0342/#new-standard-exception-generatorexit
Because PEP 342 was created before PEP 352 (the one that introduced BaseException).
Incidentally, both PEPs were implemented in the same Python version, 2.5
Is there some macro language or code generator for declarations like this?
@overload
def join(self) -> Pi[tuple[()]]: ...
@overload
def join(self, a: Pi[A]) -> Pi[tuple[A]]: ...
@overload
def join(self, a: Pi[A], b: Pi[B]) -> Pi[tuple[A, B]]: ...
@overload
def join(self, a: Pi[A], b: Pi[B], c: Pi[C]) -> Pi[tuple[A, B, C]]: ...
@overload
def join(self, a: Pi[A], b: Pi[B], c: Pi[C], d: Pi[D]) -> Pi[tuple[A, B, C, D]]: ...
@overload
def join(self, a: Pi[A], b: Pi[B], c: Pi[C], d: Pi[D], e: Pi[E]) -> Pi[tuple[A, B, C, D, E]]: ...
@overload
def join(self, *pis: Pi[A]) -> Pi[tuple[A, ...]]: ...
I'd like to write something like
def join(self, *!X) -> Pi[!tuple[X]]: # A B C D E
...
and have it generate all that boilerplate
You could preprocess the code and then exec it, or use a custom #coding thingy
I mean... yeah, but the whole point of that declaration is so that a typechecker understands it. I'm asking whether there's a tool that could generate such code in any form.
no, Python's generics aren't powerful enough for this sort of thing
e.g. you can't define a function that takes any number of arguments and returns a tuple of them, like f(4, 2, "foo") -> tuple[int, int, str]. You have to write these overloads.
Hmm.. I guess you could write a script to generate those
getting flashbacks
I see that kinda thing in a certain JS library
but, to answer your question...no, sorry.
I think could do this specific thing in Typescript, btw 🤔
...you can?
here https://github.com/decorator-factory/typescript-binary-schema/blob/master/schema/index.ts#L169
I have a function that takes {a: Message<A>, b: Message<B>, c: Message<C>, ...} and outputs Message<{a: A, b: B, c: C}>. So these transformations are possible
it looks a little bit terse, but it's possible
K extends keyof T always makes me a bit weak at the knees
😂 feels so good
but
the thing is
you can't use the ..., right
that was what I was thinking of
@gleaming rover In TS, ...args are hinted as an array, unlike in Python. Which generally is a bit counterintuitive, but here it makes a certain thing possible
if it wasn't like that, I could've used an array
I guess they could've went with K ⊆ π(T), but that would look a little bit more cryptic
pi = dependent type?
is that what it's called
it's a "projection"
like, a function from a record or tuple to a single element
doesn't make much formal sense here, just for the sake of using greek letters
Dependent typing is when a type depends on a value, if I understand it correctly.
yup
it is
which was what I associated pi with
so I was a bit confused
Hi here. I have a website that runs with a python backend. It does some compute heavy stuff (numpy, tensorflow, etc.). It is currently packaged as docker images
I would like to package it as an electron app. Do you think such python application can be correctly packaged as windows executable ?
That makes me wish there was a type annotation to indicate value bounds, or sizes but I guess that isn't a type though
I think there’s something like that, they use something similar to typehint the mode argument of open
@swift imp pydantic models can do this
class Pie(BaseModel):
flavor: Literal['apple', 'pumpkin']
Pie(flavor='apple')
Pie(flavor='pumpkin')
Yeah but you can't say like an integer between 1 and 50 right?
Or an array of length 10 in dimension 1
They added a whole operator for matrix multiplication but won't supply stuff like Matlab argument blocks where you can specified shape type and value range
bigger_int: int = Field(gt=10, lt=50)
a_list: List[str] = Field(max_items=10)
So if 2 vegans get in a fight is it really called beef?
Not the channel for this my guy, try off topic
Has anyone read anything new on the steering councils decision of patmat?
if python is built on c how do lists work
like, in c all memory is defined when you malloc() them. you cant just append to an array like you can in python
unless append() is tied to realloc()
that would be very inefficient tho
since realloc() copies the array each time
does it??? noooooo
Lists arnt contiguous memory at the c level
yo
More akin to a bunch of pointers iirc
It does reallocate the list to extend it, but it amortizes it over multiple additions
Instead of extending the underlying array by exactly 1 item, it effectively uses a multiplier
I don't remember the actual value, but you can imagine that it, for example, doubles the underlying array once it reaches full capacity, and then just remember the actual capacity vs the amount of occupied slots
well, the array of pointers is contiguous
But Python only has "reference semantics", not "value semantics", so it can only store pointers
Well, C++ has dynamic arrays as well (std::vector), they don't allocate items one by one either.
lists are overallocated to prevent that
lists in at the C level look like this: refcount, <class list>, list_length, Pointer<ptr_arr>, ptr_arr_size https://github.com/python/cpython/blob/master/Include/cpython/listobject.h#L5
list_length is the count of items in the ptr array that are actually in the list, ptr_arr_size is the size of the allocated ptr_arr
The list contains a contiguous dynamic array of pointers to Python objects. It does realloc as the list grows, but the trick it plays is that each time it grows, it grows by a multiple of the current size. That means that as the list gets larger reallocations become more expensive (because they need to copy more stuff) but rarer (because the amount of new items needed to trigger each subsequent reallocation is larger than the last). This leads to what is called "amortized constant time" appends
Which means that, even though some appends will be slower than other appends, when considered on average across many append operations the amount of time each one takes on average does not vary according to the size of the list
Good afternoon everyone I am new to the discord, but I am trying to make a batch file with a python script using Selenium to do web scraping. From what I have researched I can just create a notepad file that has the python.exe in quotations and the .py script in quotations and save it as a .bat file. When I do this the file saves correctly, but never opens the web driver firefox.exe I believe it is because it cannot find the firefox.exe when running the batch file. If anyone has any tips or another way to create a .bat please let me know or I can add you to a current discord call I am on so you could perhaps direct me to doing the correct thing. I am rather new to python so any helps is appreciated.
This channel is strictly for discussion. Try opening a help session for your question; see #❓|how-to-get-help
we have to be able to access it soo its valid
>>> t = (1, 2)
>>> a, b = t
>>> a
1
>>> b
2
>>> a, b, c = t, 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
``` why is this not possible
use *
because t, 3 is ((1, 2), 3). You can unpack it like (a, b), c
a,b,c = (*t,3)
to construct (1, 2, 3), you would need ^
a, b, c = *t, 3 the parens are not needed though
ooo
Hi
Hello, this channel is for discussing Python at a high level. What within that topic did you want to talk about?
Could Python or robloxpy be used to execute scripts into roblox games?
No. RobloxPy is just doing usual stuff you can normally do in roblox
Does Python have an optimisation for concatenating a string to an empty string?
In my brief testing, it seems to return the same string instance when this is done
is this behaviour that I can rely upon?
!e ```py
s = '\n'
s2 = '' + s
print(s2 is s)
@charred wagon :white_check_mark: Your eval job has completed with return code 0.
True
If you're not working with subclasses you'll get the same object back https://github.com/python/cpython/blob/998ae1fa3fb05a790071217cf8f6ae3a928da13f/Objects/unicodeobject.c#L11659-L11666
Thanks
@charred wagon how would you take advantage of relying on that?
Was looking at a loop which used x += y and sometimes needed to reset x to an empty string.
Not really taking advantage of it I suppose
I was wondering if it would do a wasteful copy of the y string to create a new object in that case
For all I know, even if it did copy, conditionally assigning instead of concatenating may be slower still 🤷♂️
i think you are safe, and you are right that extra work in python will be worse
damn that's cool
I mean, was this a string concatenation being done in a loop? If so, it is already really terrible, since each new string concat is an O(n) operation as you have to make an entirely new string
If you need to construct a string part by part, you could use a list to hold all the pieces and use a join at the end.
Interesting, I thought strings in python were represented as character arrays in c, so the concat would be faster, why aren't they?
Strings being stored as arrays has no bearing on the "work" that goes into a concat. If you notice, even in the realm of C arrays have fixed length, and when you try to combine two fixed length arrays that are maxed out, you must get a new memory allocated to hold the combined array. However, purely speaking from the realm of python, strings are explicitly defined as immutable
So the idea of "extending" a string inplace wouldn't even apply
This isn't strictly true. If there is only one reference to the string, CPython 'cheats' and just extends the existing string.
I'm not sure how it's implemented in practice, but if they use a dynamic array, this is O(1) per character appended when amortised.
Try timing the following two code snippets:
old = 'a' * 10**6
new = ''
for c in old:
new += c
old = 'a' * 10**6
new = ''
ref = new
for c in old:
new += c
ref = new
Is this an implementation detail or can this behaviour be relied upon?
Also, i must say it's very interesting, i never knew we had this
Erm, I don't know to be honest. I'd have to check whether other interpreters have this optimisation.
Does mypy TypeVar allow having a generic with an upper bound, that includes the bound type itself, so that assigning instances of the base (bound) class is allowed?
I've been looking for half an hour without finding anything.
You mean this?
F = TypeVar("F", bound=Callable[..., Any])
def g(f: F) -> F:
return f
Not quite, I have this class:
CT = TypeVar('CT', bound=DeviceConfig)
class Device(ABC, Generic[CT]):
def _get_config_class() -> Type[CT]:
return DeviceConfig
But I get Incompatible return value type because DeviceConfig is not included in CT (only subtypes are allowed)
It's an implementation detail, other interpreters may not have that - PyPy, for example, doesn't extend existing strings
CPython checks the refcount and modifies in-place if there's only one actual reference
@cold forum pretty sure the reason for that is that the type variable of the generic class get's filled at the call site, so if you had Device[SubclassOfDeviceConfig] that implementation would be incorrect.
🤔 But DeviceConfig is not an ABC, so I'd like to use it as a default fallback on the base Device class, where a subclass of Device (say class SubDevice(Device[DeviceConfig]):) doesn't specify a subclass of DeviceConfig.
I am pretty sure the type checker is not powerful enough to do this.
nah, you can't do that
Weird, I don't understand why there's no option to allow TypeVar(..., bound=basetype) to take basetype as well
wait
a type variable doesn't mean any type fulfilling the bound, a type variable means a single specific type that the user chooses
and the user may not choose DeviceConfig.
yeah
Yes, but the bound= as far as I understand means the chosen variable has to be a subtype of the bound
Right. But if you have a Device[MyCoolDeviceConfig], the method returning CT must return a MyCoolDeviceConfig
Mmmhh... so that method in the base class, returning DeviceConfig, can't exist because subclasses might want some other CT type
Yes.
You can just make the return type annotation to be Type[DeviceConfig]
What do you want to do, in general?
Well, I have various base classes Device, DeviceConfig, DeviceLog, some of them ABCs. And actual devices are subclasses with specific subclasses of logs etc.
So I was using generics on the base Device class to conceptually link them together basically, for better type checking
The problem with your definition of Device is that if you have a Device[CT], its config has to be a subtype CT, not just of DeviceConfig
Just like if you have a Dict[K, V], its keys method must return a keys view of K, not a keys view of Hashable.
Yeah, actually the whole class definition looks something like this:
CT = TypeVar('CT', bound=DeviceConfig)
LT = TypeVar('LT', bound=DeviceLog)
class Device(ABC, Generic[CT, LT]):
...
But while DeviceLog is an ABC, so it never gets directly assigned, DeviceConfig isn't. Maybe I should make DeviceConfig ABC too, and have something like class DefaultDeviceConfig(DeviceConfig), and have return that in the base factory method instead?
So i'm working on a small script that takes input. And I'm using regex to verify that the input matches a pattern. Now i want it to match the pattern T.X.Y, with T being EITHER b, c or r and the X and Y being any lenght integers (both positive and negative). I got my regex to ALMOST work, except now the T doesn't just accept b, c or r, but also br, which should be invalid. The regex is as follows.
re.search(r"[bcr]\.-*\d+\.-*\d+", uinput). uinput is the input() from the user
as a few examples, the input b.1.500 is valid and is accepted. r.-300.20 is valid and accepted. d.20.-3 is invalid and rejected, but cr.50.-30 is invalid but accepted
anyone knows how to make a character from a class in regex match just ONCE?
feel free to @ me when you know
@cinder ferry you need to anchor your regexp, because anything before will also match
re.search(r"^[bcr]\.-*\d+\.-*\d+$", uinput)
ah right, thanks :D
also, you probably want -? and not -* because --- will match and you probably don't want that.
i just want the - 0 or 1 time to indicate a negative integer @lapis hound
right.
that's why you should use ? and not * because * will match 0 or more, which could be >1.
re.search(r"^[bcr]\.-?\d+\.-?\d+$", uinput)
? matches 0 or 1 time only
and ? was 0 or 1?
right thanks
yeah i'm still quite new to regex so this is a learning expedition for me
right so the ^and $ are so it doesn't match anything before and after
the ? to do {0,1}
but do you know a way to match if a single letter is either b, c or r?
i assumed it was possible with classes, but maybe not. @lapis hound
[bcr] will
you'll see that after adding ^ at the start of the regexp, it'll no longer match cr.50.-30
ah so it was matching the c in bc, and then the b was because it would match anything before too?
the reason cr was matching before is because everything before r.50.-30 would match
right that makes sense
you could test it with uinput = 'this will r.50.-30 match your regexp' if you use the regexp without ^ and $
right
>>> uinput = 'this will r.50.-30 match your regexp'
>>> re.search(r"[bcr]\.-?\d+\.-?\d+", uinput)
<re.Match object; span=(10, 18), match='r.50.-30'>
you may want to input().strip().lower() to get rid of any stray whitespace
if you're handling user input
also, not sure if input() removes the trailing carriage return (the \n)
i don't think it does
looks like it does.
but my regex seems to work now and reject any suffix characters
>>> test = input()
testing
>>> test
'testing'
it doesn't include the carriage return at the end of the string
oh wait i read your statement wrong
i thought it said something along the lines of it keeps the trailing \n
compared to, say, sys.stdin.readline() which does include the newline.
>>> import sys; test = sys.stdin.readline()
testing
>>> test
'testing\n'
i guess now i can take a look if i can make the program repeat, i guess just a simple while True and a continue statement so it restarts
well thanks @lapis hound for the help. Your suggestions definitely make sense
Good luck with the rest of your project.
thanks
it's just a small script i wanted to write after someone gave me the idea yesterday lol
each time I read regexes, I die a little inside
Why regexes are awesome
Regexes are so awesome they're used extensively in DNA sequencing
we should debug the rpt nodule so we can access the database
well, they're easier to read if you understand what problem they're meant to solve. But I agree that they're quite cryptic in isolation.
if i give you just
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
your probably won't understand a single thing
if i give you this to say this is the finite diagram of this regex you might understand it slightly better
the issue is usually with editing regexes
if i say that's currently the official regex for recognizing email adresses you might understand it even more
i've updated my regex to now be the following (^[bcr][.,\s]-?\d+[.,\s]-?\d+$)|(^b[.,\s]-?\d+[.,\s]-?\d+[.,\s]-?\d+$)
and this is pretty much my first regex i ever wrote, and it's actually easy really
yes i know i can make the regex smaller
let me do that rn
In my case it doesn't make a difference in practice because the string tends to be re-assigned at the end of every iteration.
How hard is it to package a python app with deps such as numpy and tensorflow, as a windows executable ?
quick question about Django models. you can do Users.objects.filter(...) or Users.objects.all() i know objects is a django Manager but in terms of just python mechanics itself. in this context, Users is not instantiated. what is objects because it can't be an instance variable. but it's usable as if Users is instantiated.
Your question is better suited to #web-development
it's not a web development question. it's a python question. it's not about django itself. i'm using the django implementation as an example. the question is, if Users is not an instantiated class, how are you able to call objects which returns another class?
If you just want to know how to do something like this, it can be a class variable, i.e.: ```py
class Foo:
a = 5
Foo.a # --> 5
But Django is fairly complex, and it's handled these models are handled with metaclasses which are basically constructors of classes themselves. All you basically need to know is that these `objects` attribute was assign to the class itself with some metaclass, and the `objects` type itself can really be anything, it can be an instance of some other django class, or a fucntion, etc.
Would this be a good way of making hashable lists, or are there some issues that could arise from this?
I also wonder if python doesn't already have something like this somewhere in stdlib, so I could abstract this logic away
class hashable_list(list):
instances = dict()
def __new__(cls, *args, **kwargs):
new_instance = super().__new__(cls, *args, **kwargs):
hash_value = hash(new_instance)
cls.instances.setdefault(hash_value, new_instance)
return cls.instances[hash_value]
def __hash__(self):
total_hash = 0
for element in self:
total_hash += hash(element)
return total_hash
I'm specifically interested in the possible issues from __hash__, I do realise that I'm returning the same, mutable instances, so if this list is created and adjusted, it would adjust all of the other lists, that is intended behavior
Summing hashes isn't good because 1. it disregards the order of items in the list 2. there are multiple ways to get the same sum, so you'll get hash collisions
yeah, I thought that might be an issue, but what would be the preferred way to do it then?
I don't know, sorry.
For example, you could do this
def __hash__(self):
total_hash = 0
for element in self:
total_hash = total_hash * 2 + (hash(element) + 1)
total_hash %= 2**64
return total_hash
or... just this:
def __hash__(self):
return hash(tuple(self))
But yes, you're going to get into trouble with this if you're mutating a list.
how does tuple implement it's __hash__?
I was just wondering why something like
a = 0
def function():
a = a + 4
Doesn't work, since for example having a + 4 in the function would work.
Why is it only when you use a = a that it searches for a in the local scope rather than getting the value defined in the scope outside of the function.
My guess is that this is just a way to have consistent behaviour
It forces you to be more explicit about your intent
Yeah that sounds reasonable
Its better than JS, you can unintentionally affect global variables if you forget to define variables with var in your function
it's defined to be that way:
If a name is bound in a block, it is a local variable of that block, unless declared as
nonlocalorglobal. If a name is bound at the module level, it is a global variable.
and as for why it's defined to be that way - that's the only way for there to be local variables at all.
def foo():
x = 1
return x
If this rule didn't exist, would it be possible for this to assign to a global variable instead of a local?
I think you misunderstand the question
Yeah slightly, although I did just have a thought
The example given could have used a from the global scope and then create a locally scoped variable
What i was trying to say with my answer is that those kind of semantics would be inconsistent and confusing
Is this behaviour beneficial fallout of the way variables are created. Like for example a = a + 4, does it initialise the local a before attempting to assign to it a + 4, leading to it looking for the local variable a rather than getting the one defined in the global scope
local variables are determined at parse time, not when the function is run.
ah ok
the existence of an assignment to a particular variable name, and the absence of a global or nonlocal for it, makes it a local variable - at the point when the function is parsed, and the bytecode for it is created (because the bytecode is different depending on whether it's looking up a local variable or a non-local or global variable)
you're right that it could make a reference to a local variable before it has been assigned look it up in an enclosing scope, I suppose
but doing that would actually be kinda tough.
quite tough, really. py x = 5 def foo(): if random.random() < 0.5: x = 10 print(x) If you wanted this to print 5 or 10 with a 50/50 chance, it would need to generate different bytecode for the x access in the print(x) line depending on whether or not the if block was entered, because accessing a local variable uses different bytecode than accessing a global variable.
ah yeah that would be tricky
the other thing I guess it could do is initialize local variables with a reference to a global variable of the same name, but that would make calling functions much slower - it would imply a global lookup for every local variable every time the function is called.
I suppose it wouldn't be entirely unreasonable for LOAD_FAST to fall back to LOAD_GLOBAL instead of raising an UnboundLocalError?
hmm
well, if you have
def f():
x += 2
x = 1
couldn't it just raise a compile time error?
It is way more complicated because of the mutable nature of Python
For example if you add an exec("x" + "= 0") at the top
sure
But, for example, Python can issue syntax warnings in some cases:
!e
def f():
[{}]()
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
<string>:2: SyntaxWarning: 'list' object is not callable; perhaps you missed a comma?
maybe it could do the same for this:
def f():
x += 2
x = 1
Well, in this case you can be 100% sure that it will result in an error
While variables can be "tampered"
You need to account for scoping, control flow, and stuff
In simple cases it can issue warnings, like here.
Where you probably just forgot a global a
That's a whole layer of analysis while this warning is probably just detecting a pattern in the AST
@undone hare ...in the same way that Python doesn't do full type checking and inference, but it can spot trivial stuff like ()().
which is likely a typo
Well, this doesn't need any advanced analysis, by just looking at the ast you know that it will result in an error
The warning you're pointing to only has to look at a single statement, but the one you're proposing would need to look at all previous (to figure out if the variable has not been assigned already within the function) and future (to figure out that the variable is a local variable) statements in the function.
hm, yeah, that's a bit more complex
however, static analysis tools (even flake8 and such) can point out when I do a mistake like that, so that's probably not very hard
A static analyzer can take much more time to do that sort of checking than the interpreter itself can afford to do. Slowing down all compiling in order to introduce a relatively expensive check for a relatively rare mistake is a hard sell.
If I'm making a class to represent a webhook and I wanted to make all of the webhook keys class variables but all of the webhook keys are in camelCase, would you convert them to snake_case to stick with Python conventions or keep them camelCase to make it easier when working with the documentation that sent the webhook?
Why are that camelCase in the first place?
It's coming from a json object webhook from another server.
Hmm
I'd make the internal attributes snake_case
Well, the Python representation snake_case
I can keep their convention so their extensive documentation is consistent
I have a very deep aversion for camelCase
Great, already made the function to convert the dict keys to snake
Is there a way to convert all the attributes of function.__code__ into an actual function object?
I see all these things like co_cnlocals, co_code, co_stacksize, etc..
And I think that it's possible for me to do something like
function = create_function(all of the __code__ attributes)``` and it'll create a fully working function
Yes, use types.FunctionType(...)
Could you give an example on this?
new_function = FunctionType(code=other_function.__code__, globals={})
What about co_code
that is what LOAD_NAME is for (for names whose scopes can't be determined at the compile time)
that looks interesting
Well you need the entire code object
You can make one yourself using the compile() built-in
:same:
Okay your example made a function using __code__, but is there a way to make a function by putting the attributes of __code__ in there?
not __code__ itself
are you looking for something like CodeType.replace?
Depends what it does
Yeah with CodeType(code args...) I guess
!d types.CodeType.replace
replace(**kwargs)```
Return a copy of the code object with new values for the specified fields.
New in version 3.8.
I don't see that point in that if you already have the code object
it basically does the CodeType(co_attr=old_code.co_attr, co_attr2=old_code.co_attr2, ...) job
there are plenty of open sourced repositories on github or other platforms like that, but this isn't the correct channel to ask in, this channel is focused on questions about python implementation itself, and questions regarding that
I'd say #software-architecture would be more fitting for this type of question
@summer hedge 
thanks. Moved it there
hi
How do I state the argument name for a multi-arg created with an asterisk when calling the function with the multi-args?
Example:
def func(*args):
print(args)
func(args=82, 27, 7.23, 'ha2£')
That's not possible. Keyword arguments are made when you want to make it clear to the reader what you're passing in, so that you don't end up doing draw_foo(1, 2, False, True, True, False, True).
Why do you want to do that?
Random question
Why does the AssertionError exception inherit from Exception?
Given the whole mentality of the purpose of assertions, what they are used for, it seems like AssertionError should be outside that hierarchy, the same way that say KeyboardInterrupt is
assertion failures indicate that a precondition was not met, and basically that the program itself is invalid, so it shouldn't be ok normally to just try to "handle" the error
You may find insights into that by digging through mailing lists surrounding PEP 348 and 352, but based on the PEP contents it doesn't seem this was ever even considered.
personally I don't see "precondition not met" as necessarily so extreme a fault that the program should terminate
e.g. division has a precondition that the divisor must be nonzero, but you get a ValueError that you can handle
i only agree because the language is so dynamic in nature
IMO assert is just shorthand for "raise a special kind of exception if this condition is not true"
it lets you pass arguments without spending a bunch of runtime checking their properties extensively
if this was say C/C++ and i tried to divide by 0, i would 100% except some assertion before that to crash the program - it's a programming error, using an api out of contract
i've written an incorrect program
just with python, imo the term "incorrect program" is slightly looser
so catching assertions is more ok
i do agree with this tho, basically what it ends up being 🙂
hm
would it always be a programming error?
okay so the case I'm thinking of is
say you pull data from some outside data source and you get only the records that fulfil some criteria, and you want to compute summary statistics, which involve division and would be meaningless if there were no matches
and an exception is more meaningful?
Division by zero is defined behavior on IEEE 754 floats.
hmm you're right :/ ok i stand by what i said tho, and just feel my example was a little off
not sure what would be idiomatic for C/C++
but what I meant to highlight was that it's not necessarily bad code?
do it in python; you say that no matches is meaningless, but i assume an exception would also have no matches?
which is what you get if u divide something by 0 (unless your thing automatically translates it to a NaN or something)
this happens to be the case in numpy (which is neither here nor there)
Assertions in Python just aren't very useful. Just don't use them. 🤷
but anyway...I guess?
pytest?
assert is a sanity check that can be turned off at runtime. Using it in production code for anything other than an a nicer error message for something you would handle either way is wrong.
For unit test suites, clearly they're pointless if someone turns off assertions, so they're the exception to the rule.
Unless you're in control of how the program that uses assert is started, you can't know what assert will do, so it's safest to not use it.
why is it safest not to use it? it's a choice between a programming error (being propagated) and an exception
make it actual error handling that throws a real exception
Asserts can be turned off
You should raise an exception directly.
Cause you cannot rely on the assertion being enabled
