#internals-and-peps
1 messages · Page 115 of 1
So I'd say that conda is basically a complete solution, the others (afaik), you have to have something else in the mix to make sure the native side of things is consistent and has all your dependencies
For just working on some personal projects on your own machine this probably doesn't really matter
Conda is a bit of a weird tool, to the point where I feel like Continuum (the company behind it) doesn't understand the value of what they have created, or doesn't know how to make use of it
A binary package manager that can install packages in any location on the system is not a trivial accomplishment
And while it is tremendously useful for data science, there's no reason it shouldn't also be useful as a general dev tool
I have high hopes for the Mamba project
I think they understand the value
That's why they released conda separately
We use it extremely extensively
IMHO if you're not going the docker route conda really seems like the way to go
Unless you can really guarantee full control and homogeneity over all the machines you ever run on
We use conda primarily as a C++ environment tool and second for python
yeah no reason for them to have made miniconda if they didnt understand the value
"here is our amazing conda, without any of the data science or bloat"
what more can ya ask for
hi i was wondering if anyone can help me with this code
Hey @distant coyote!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
Hey @distant coyote!
Uh-oh! It looks like your message got zapped by our spam filter. We currently don't allow .txt attachments, so here are some tips to help you travel safely:
• If you attempted to send a message longer than 2000 characters, try shortening your message to fit within the character limit or use a pasting service (see below)
• If you tried to show someone your code, you can use codeblocks
(run !code-blocks in #bot-commands for more information) or use a pasting service like:
!code-blocks
Here's how to format Python code on Discord:
```py
print('Hello world!')
```
These are backticks, not quotes. Check this out if you can't find the backtick key.
Hey @distant coyote!
Uh-oh! It looks like your message got zapped by our spam filter. We currently don't allow .txt attachments, so here are some tips to help you travel safely:
• If you attempted to send a message longer than 2000 characters, try shortening your message to fit within the character limit or use a pasting service (see below)
• If you tried to show someone your code, you can use codeblocks
(run !code-blocks in #bot-commands for more information) or use a pasting service like:
If you give a default variable a global or built-in value, is that any different that just assigning the variable in the function?py def f(local_print=print): local_print("something")
is that any different from this?py def f(): local_print = print local_print("something")
My idea of how it works is, there’s an array of local variables with the names of all the local variables, and the values which all start as null or something like that. But for default arguments, the values start as whatever object you give as the default value. Is that right, or is that not how it works?
Actually, could you use that even for local variables? Could you just assign all the local variables to default argument values and then the function never needs to assign any values, it just immediately has them assigned?
Sorry, I mistyped it earlier. Now it’s correct
They will both end up in locals, I don't think there's any difference between them beyond how the assignment is handled.
I noticed that the bytecode doesn’t have any part where it assigns the default values in the default variable functions, but I’m not sure if it still had to assign them and it just doesn’t show in the bytecode
!e It's done as a part of building the function with MAKE_FUNCTION
import dis
dis.dis("""
def f(local_print=print):
local_print("something")
""", depth=0)
@peak spoke :white_check_mark: Your eval job has completed with return code 0.
001 | 2 0 LOAD_NAME 0 (print)
002 | 2 BUILD_TUPLE 1
003 | 4 LOAD_CONST 0 (<code object f at 0x7f2aa3c60920, file "<dis>", line 2>)
004 | 6 LOAD_CONST 1 ('f')
005 | 8 MAKE_FUNCTION 1 (defaults)
006 | 10 STORE_NAME 1 (f)
007 | 12 LOAD_CONST 2 (None)
008 | 14 RETURN_VALUE
It will have to use load_global for the print but after that accessing local_print is the same
It’s exactly the same except for LOAD_FAST for print instead of LOAD_GLOBAL
!e ```py
from dis import dis
def f(x=1, y=2, z=print):
z(x + y)
def g(x, y):
print(x + y)
dis(f)
print()
dis(g)```
@sand goblet :white_check_mark: Your eval job has completed with return code 0.
001 | 4 0 LOAD_FAST 2 (z)
002 | 2 LOAD_FAST 0 (x)
003 | 4 LOAD_FAST 1 (y)
004 | 6 BINARY_ADD
005 | 8 CALL_FUNCTION 1
006 | 10 POP_TOP
007 | 12 LOAD_CONST 0 (None)
008 | 14 RETURN_VALUE
009 |
010 | 7 0 LOAD_GLOBAL 0 (print)
011 | 2 LOAD_FAST 0 (x)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/fujovozome.txt?noredirect
The place where default values are assigned to the local variables is during the argument parsing, where it checks the tuple of default args in the function object:
https://github.com/python/cpython/blob/736ed6f7a9f465ba728198e8bca81e5fbe71bc37/Python/ceval.c#L5005
As others have described the default values are evaluated at the time the function is defined, which is the main difference between assigning it inside the function.
Python/ceval.c line 5005
/* Add missing positional arguments (copy default values from defs) */```
Is there a good way to explicitly declare that a class implements a protocol? This is what I'm doing right now:
# auth.py
class OAuth(Protocol):
async def request_link(self) -> str:
...
async def submit_code(self, code: str, state: str) -> Optional[User]:
...
# google_auth.py
class GoogleOAuth:
def __init__(self, config: Config):
... # actual implementation
async def request_link(self) -> str:
... # actual implementation
async def submit_code(self, code: str, state: str) -> Optional[User]:
... # actual implementation
_: type[OAuth] = GoogleOAuth
At that point it's basically just a mixin or zope-style interface, no?
I would feel weird inheriting from it without abc semantics
Unless the method has a sensible default implementation I would rather have an error at class definition time than wait to have a method that inexplicably and unexpectedly returns None
In which case, what's the point of using the protocol at all? To maybe support misbehaving library authors who don't want to inherit from the right parent classes?
It would be nice if you could statically indicate that a class is expected to implement a protocol, without actually inheriting from it at runtime
Is there a net benefit for that though? If you are implementing a protocol, and then using it in another context then the type checker would probably catch if you are missing stuff
explicitly declaring only seems good as far as documentation goes
That's kind of my point I think? The whole point of a protocol is that it's structural, not by name
If you are designing the interface from scratch you choose between explicitly naming the interface with an abstract base class, or just documenting the interface and using a protocol
which I guess could be specified in somewhere in the docstrings, if you want to avoid inheriting (though I don't think it is likely that you'll inherit something and stuff fail on the runtime when the default method returns None, the type checker you are using would catch that misusage up).
yep
Hm... well, I guess it's an issue with pyright -- it skips checking the protocol conformance if you inherit explicitly
for performance, as the author claims
I wish it was easier to extend these type checkers
I'm not sure if it's a fundamental issue in the way a type checker has to be designed
That's pretty strange
I would expect if you inherit something explicitly and don't fully implement it then the type checker should complain
But re protocols it is strange to explicitly declare protocol conformance, the whole point of protocols is that you don't do that
ABCs are for explicit
And the benefits are not just documentation, there's a whole debate on whether structural polymorphism like this is actually a good idea, and in the end most languages say "no" because it's a very rare feature in statically typed languages
Generally interfaces aren't just about syntactic requirements, but also semantic requirements. Structural/implicit opt in is basically hoping that everything that meets syntactic requirements also meets semantic requirements
As opposed to being explicit which is a programmer explicitly asserting that the semantic requirements are met
I do kind of like the idea of statically-checkable protocol implementation though
In a way it could almost obsolete ABCs
You don't have the MRO problems that you have with an ABC and inheritance
With a static checkable Protocol, the type checker would tell you whether that method is implemented or not, regardless of where in the method resolution order it is
!d typing.runtime_checkable
?
@typing.runtime_checkable```
Mark a protocol class as a runtime protocol.
Such a protocol can be used with [`isinstance()`](https://docs.python.org/3/library/functions.html#isinstance "isinstance") and [`issubclass()`](https://docs.python.org/3/library/functions.html#issubclass "issubclass"). This raises [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError "TypeError") when applied to a non-protocol class. This allows a simple-minded structural check, very similar to “one trick ponies” in [`collections.abc`](https://docs.python.org/3/library/collections.abc.html#module-collections.abc "collections.abc: Abstract base classes for containers") such as [`Iterable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Iterable "collections.abc.Iterable"). For example:
```py
@runtime_checkable
class Closable(Protocol):
def close(self): ...
assert isinstance(open('/some/file'), Closable)
Oh, statically checkable
Well, type checkers already understand protocols, it's just that Pyright doesn't do the checking if you explicitly inherit the protocol
mypy offers a ~decent API, not sure if they released it publicly but I've written off a few plugins for an internal code base and they work pretty well.
@grave jolt yeah I would want the opposite, @typing.implements(MyProtocol)
Good to know, I don't know anything about programming language theory but could be interesting to mess with
It doesn't obsolete ABCs, because like I said, having to "opt in" is intentional
A lot of new languages of the last few years for example could have opted for structural polymorphism a la go, and have decided against it, because they don't like how it's implicit
I prefer it explicit as well, I think though in python given that the actual language is duck typed, there is obviously extra benefit to protocols in some cases
this is pretty cursed 👀
https://github.com/python/cpython/blob/3.9/Lib/urllib/parse.py#L616-L619
Lib/urllib/parse.py lines 616 to 619
if not string:
# Is it a string-like object?
string.split
return b''```
Yikes @ urllib in 3.9
WTF
"structural subtyping" 😄
python isn't always about performance?
what even is that? shouldn't it at least be if not hasattr(string, 'split'): raise SomeInformativeError(...)?
it looks like that might just raise an esoteric attribute error
If it's not a string, return empty bytes. I don't believe the line string.split does anything.
Well, it raises an error if the attribute doesn't exist. That's probably why that line exists
>>> class C:
... def __bool__(self):
... return False
...
>>> c = C()
>>> from urllib.parse import unquote_to_bytes
>>> unquote_to_bytes(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\Mark\scoop\apps\python\current\lib\urllib\parse.py", line 616, in unquote_to_bytes
string.split
AttributeError: 'C' object has no attribute 'split'```
Ah, yea. Why not raise an error?
You mean, why not be more explicit about it? I don't know I didn't write urllib 🤷
God bless
Why not just catch the exception when it would naturally happen 3 lines down?
Or check hasattr??
Not like you really need to care about TOC/TOU issues (theoretically in a multithreaded environment you could assign a split attribute while this is executing.....)
urllib.parse is used all the time still
it's not wrong, it's just a strange way to write it.
It does just raise an AttributeError if the thing doesn't support .split - that's not completely unreasonable; that's a normal way for duck typed functions to fail if you pass the wrong type
Oh i bet it's because they wanted to use the "natural" attribute error while using the fast path of returning empty bytes
yeah - if this fast path didn't exist, it would fail with the same AttributeError once it hit line 622
Someone brought this up https://bugs.python.org/issue9301
raising a TypeError with a proper message seems better than raising an AttributeError (maybe check if not isinstance(string, (str, bytes)): raise TypeError(...)?);
Response was
The AttributeError on unquote() is backward compatible with 2.6, 2.7 and 3.1. (issue 9301 is about backward compatibility)
seems pretty reasonable to me.
Static methods have no access to self but otherwise have no benefit memory wise right
Yep
Well, they have a very very minor performance benefit over normal bound functions
PERFORMANCE? time to make every single method static
lmao
You can get the same performance benefit with regular methods by just calling type(obj).method(obj) instead of obj.method()
Haha ikr, my senior at work raised it while I was planning out my rejig of our core runner, so I went to look it up
When importing a class from another file and creating an instance of it, does it come with the imports in that file as part of the instance?
the entire module that the class comes from will imported, which includes all its normal import statements
is there a reason one wouldn't want an __init__.py in a dir which had python modules?
if you don't want it to be a package, for example it just has some scripts for you to use and you don't intend for the python files inside to be used elsewhere
Thanks
Actually, as an aside to this, if I'm importing a class and mutating it, and both the super class and the subclass rely on some external library, is there a way to ensure that I'm only importing these once?
In this case it's botocore
Does this work:
import superclass
from superclass import botocore
Does that leave me with one import or two
Can't seem to phrase my Google search correctly to get an answer
is superclass a module here?
anyway, modules only get imported once, if you try to import them again you just get a reference to the one that was imported earlier
some linters (pylint I think) would ignore these modules if that was the case?
Also - there would be (as far as I'm aware) no harm in having the init files in your example, it's just they might not be needed?
if you need a package you use __init__.py, if you don't need a package you don't use it
it has no harm in the same way giving your variables bad names has no harm, things still work but you might be making things difficult to understand
disagree with this - how is it similar to a poor variable?
I'm going to assume that if that's the only example, it's fine to just use as default
I can't imagine failing to understand something because of an __init__ file at least - sure - what's the issue with that?
I can't see a down side from what you've said
the intention behind packages is to organize a bunch of modules together into one cohesive "thing"
and perhaps give them better names via namespace packages
I'm failing to see the harm with using an __init__ still 🤔
like, I have a scratch folder that contains like 10 different scripts that have no relation to each other
why would I turn that into a package? I haven't structured the files in any meaningful way
you're not answering why not, but i'm happy to stop this as i'm not seeing the issue
the variable example doesn't hold imo, or at least would need explaining how a __init__ could be as misleading as dataframe = [1,2] or something
not misleading
I was thinking more like naming everything a, b, c, etc
it doesn't break anything to do that
still doesn't hold, don't think it works as an example
i mean, what you're saying is "I want to make a package because I can"
well, you can
sure, i'd have a more solid explanation of why they shouldn't in my context - as they might have in theirs for doing so
a,b,c might be reasonable names in some context, hence why i wouldn't say they're "wrong"
you know what I'm talking about though don't you
naming everything a letter of the alphabet
going to a limit case all the time doesn't make sense imo
or is pointless... sure - naming everything a,b,c,d... would be poor, but doesn't make sense in this case imo
Is the original discussion around "are there downsides to using empty inits?"
Yes - this abc thing doesn't make sense to me in that context
not empty inits, just inits in general
original question is basically "why shouldn't I just add an __init__.py to every folder with python files"
I mean, if it's a non empty init, there's no point of discussion, you need it. Otherwise it would have been empty.
Oh.
Okay, so I see two different questions.
Which one is the one? Question 1. Are there any issues with using empty inits in some package.
Question 2. Are there any issues with making an empty init everywhere I'm coding py files.
(non empty inits are, imo, by definition needed.)
For the former question, empty inits in a package sound perfectly fine to me. For the latter, I don't see why you'd want the hassle of making inits for throwaway scripts, it doesn't make sense.
Yeah - it seems fine - just wanted to check to see if there were any odd edge cases or whatever
anyway my point was that it signals your intention as the creator
https://www.python.org/dev/peps/pep-0420/#differences-between-namespace-packages-and-regular-packages well there are a few differences
i can see no significant confusion arising from having an __init__ so don't think this is much of an issue for me
it might be if you're publishing things, and it might cause issues with things like setup.py package discovery
which looks for folders with __init__.py
I'm not - but if that's the case an example could be interesting, not too sure what to search there
I mean I can only really find examples of folders without __init__.py just as a declaration of intention, like with https://github.com/pandas-dev/pandas
they have .py files in doc and web, but no __init__.py, because those file aren't meant to be imported, they're meant to be run "standalone"
I don't know if adding them would actually break anything when building pandas, though
but for scripts that use find_packages in their setup.py it would change the result
hrm 🤔 , setup.py example is interesting thanks
I think conceptually it's very important to distinguish between packages, namespace packages, and directories that are neither
doc is neither a package nor a namespace package, it's just a directory in the project tree
You could put __init.py__ everywhere in your filesystem if you wanted, but it'd just be confusing
Am I right in thinking that the setup.py file is executed when you pip install something from pypi?
yes
Someone in a help session gave me the impression that something else happens and I needed a sanity check. Thanks!
(I host all my stuff on github because I have not yet taken the time to learn how to post on PyPI)
Does it execute when wheels are used?
it's executed on the machine that makes the wheel
assuming you're using the setuptools build backend, at least.
I don't really understand wheels, but aeros mentioned that if I wanted to post a C module on PyPI that's available for Windows, I could build a wheel for it.
PyPI packages come in two forms: source distributions and binary distributions. A source distribution is just the source code, and when pip downloads the code it needs to build it - by executing the setup.py script, normally. A binary distribution contains an already built package - in the case of a C extension module, that means it has already been compiled.
and a wheel is a type of binary distribution. It basically just needs to be downloaded and unzipped, but it's already been built.
poetry is awesome, it puts all dependencies in pyproject.toml, and to publish to pypi all you need is poetry build and poetry publish
How can I execute a python program with a linter that, at the end, it gives a report for type annotations like: "this variable was expected to be a float, instead got int" etc? It didn't break the program but was a different type in the runtime
Perhaps do that type check and save it when that variable was called, then compile a report at the end?
You mean manually?
No, I'm guessing something about python's dynamic typing means your linter isn't evaluating correctly if you're only getting type results after the code has already run
I mean doing that type check dynamically at key checkpoints
I've not got super in depth experience with this tho, I think some of the helpers know a lot more about this
mypy was made for that
based on the question it seems like something like https://github.com/Instagram/MonkeyType would be more appropriate
I don't know whether it can give you the report you mention, but it can annotate code, so you'll be able to see from e.g. git diff what has changed
Sorry for the late reply. Thanks for the help
Yes I think mypy should be able to do that but haven't figured it out. I mean running mypy main.py gives linting errors as output. What I want to do is running the program with it, and getting warnings like "variable x expected to be an int but got float" etc in the runtime with real scenarios
i think you could write a decorator which checks the function annotations and emits a warning whenever the types of the arguments don't match
checking if the annotations are correct can be very expensive, or even impossible in some cases
if you typehinted something as expecting a list[int], and you received a list with a million elements, verifying that all of them are ints would be expensive
you'd also have consume any arbitrary iterator completely to check if it matches the typehint
Hi! I am working on a package with some nested modules and we import some classes and functions from deep down directly into the outermost module. But in the help strings and sphinx docs they are displayed with the full module path, e.g. scipp._scipp.core.Variable. In order to abbreviate this, we can do Variable.__module__ = 'scipp'. But I am wondering if this could have bad side effects and break some code? Also does anyone know of a better solution?
There's this project, which avoids the expensiveness issue by only checking a single (pseudorandom) item each time - that way over multiple calls, it'll check the whole structure:
https://github.com/beartype/beartype/
hello guys, can anyone help me pls?
hello guys. i know i am the wrong place but does anyone has any hacking knowledge here..i dont want to hack anyone. i just have some important queries..
There are tools like https://pypi.org/project/runtime-type-checker/, or you can write your own.
But, as hahastinkypoop said, it will be either way too expensive (think of a million-sized list) or impossible:
def foo(f: Callable[[int], str]) -> str:
return f(42)
how do you check if f is a callable taking an int and returning a string?
Hey everyone, got a question regarding imports
Say I have two files, parent\__init__.py and child.py
parent\__init__.py looks like this
import some_big_library
import other_big_library
class BaseClass:
def __init__():
raise Exception('Implement in subclass')```
child.py needs to use BaseClass as a superclass while also keeping memory from imports as low as possible (has cost ramifications)
which of the following 3 versions of child should create the least memory requirement?
child_1.py:
```Python
import some_big_library
import other_big_library
from parent import BaseClass
class ChildClass(BaseClass):
def __init__():
some_big_library.stuff()
other_big_library.stuff()```
child_2.py
```Python
from parent import BaseClass
class ChildClass(BaseClass):
def __init__():
BaseClass.some_big_library.stuff()
BaseClass.other_big_library.stuff()```
child_3.py
```Python
from parent import *
class ChildClass(BaseClass):
def __init__():
some_big_library.stuff()
other_big_library.stuff()```
And PS How do I test this for myself, I'm a little unclear
Modules are cached after the first import and the cost of names is negligible, just use what's the clearest and most readable
A senior dev at my place is adamant that there is a memory cost, I'm not sure how to prove this
I did tell him it was negligible
This is close to what I'm looking for. Thanks. I'm just want a warning though, but I'm gonna figure out a way
Is there a static type checker that can already validate whether cases are exhaustive (e.g., must cover all enum values) for the new pattern matching statement in 3.10? mypy and pyright don't seem to do so yet
I'll probably go with option 3 since it's still readable, but sidesteps his objection
I would avoid star imports as then it isn't explicit where names came from
And importing imported modules from a different module is definitely unusual, but if it keeps them happy
True
I wonder if there is a pep I can point him at that demonstrates this isn't an issue
His background is heavily in 2.7 so I suspect this was once an issue but no longer is
it shouldn't be difficult to demonstrate
consider a.py:
import hashlib
main.py:
import hashlib
from a import hashlib as hashlib_from_a
print(f"Are the same: {hashlib is hashlib_from_a}")
Brilliant, that works, ta
if this didn't hold, you'd be in trouble
Maybe python 1 did imports like that but even there I'd be surprised if they weren't kept somewhere after the first import
e.g. if you force reload a module with a type, instances of that type from before reloading will no longer pass isinstance checks against the new type
because the type was redefined
this also breaks except ErrorType checks 😔
for example:
a.py:
class MyError(Exception):
...
now in main.py:
import a
exc = a.MyError("My error instance")
try:
raise exc
except a.MyError as caught:
print(f"Caught: {caught}")
this error gets caught
import a
exc = a.MyError("My error instance")
from importlib import reload; reload(a)
try:
raise exc
except a.MyError as caught:
print(f"Caught: {caught}")
this one doesn't
because these are no longer the same type:
is it possible to invoke importlib.reload in the main thread from a background thread?
use case: continuously reload a module during interactive editing
Hey guy the software inside ATM or Self-Checkout machine are about application software development or embedded system development ?
@paper echo there used to be something that would auto reload every time it was edit, I thought
ah nice
@verbal escarp you should see what ipython does internally ☝️
however ipython might be doing it single-threaded async
i don't think that's an option in this particular case
@finite sparrow
Here's your reminder: [#internals-and-peps message](/guild/267624335836053506/channel/709904092280914030/).
[Jump back to when you created the reminder](#internals-and-peps message)
who woulda thunk
Hey guys, I wanna know if I can place custom images and text with with auto fit on a template from python
Hello, I am currently looking for replacing starlette with another python api as starlette is executing one api call twice and it's fucking up with the table queries, any suggestions? How's falcon?
sounds like a problem with your code, not with starlette
maybe the browser is making an OPTIONS request together with a POST request? Have you looked at the logs?
also, not on topic here, claim a help channel (#❓|how-to-get-help) or see #web-development
Try #web-development. This channel is about the Python language, not libraries or frameworks.
Hi, i'm having a hard problem with a program, it uses science and engineering libraries, is it the right place for that question?
the program i'm using is openMotor (which the source is in github). I need to modify the code so it can receive a custom geometry in a special format (called spline, by the code).
It isn't exactly data science (and software engineering). It's a tool for a research in rocketry, is #data-science-and-ml about it? (i'm new in this server)
it's not exactly the topic, but it's the most likely place you can get help with numerical computing, simulations, etc. this channel is about the python language itself.
Hmm... Thanks 👍
wow great suggestion! it's almost like I cannot read my code haha 😐
the code is supposed to do exactly what is needed, while request is made it makes two requests simultaneously and the queries get executed twice, it's a simple request made from android app
help channels are useless and I came here cus python general is filled with normies, hence this seemed like a good place where people actually have something to suggest
I'll try #web-development
@summer oak help channels are only as useful as your question is answerable
Since you can use dict.__iter__(odict) with an OrderedDict to get a regular dict iterator from it when you just want to quickly iterate through it without caring about the order of the keys, is it right to say that the only thing you have to sacrifice with OrderedDict is some extra space? Or would it be wrong to say that?
you sacrifice the {} syntax, and you express the wrong intent to your users
But I mean in the case of really wanting efficient access of the values at either end and being able to efficiently move items to either end
dict.__iter__(odict) is kinda weird, ordered dicts aren't actually the same as regular ones, they have a completely different implementation using a linked list.
Yeah
If you pass dict.__iter__(odict), to next then it won’t reflect if you’ve been using move_to_end because it maintains order like how you said
But I mean specifically in the case of that not being a problem
And I mean, if it was, you could always use the normal OrderedDict iterator
But it’s slower
I was thinking about what if you had a regular dictionary where you wanted to get the first or last keys, but you were frequently removing keys specifically from the beginning or end. If you do that with a regular dict then accessing from either end is O(n)
it really depends on the implementation detail, to answer whether it's wrong to say that
the fact that it's the same dict iterator isn't enough information to conclude
if the implementation is more of a linked list approach then the data you're iterating over could be scattered in memory
when you construct an iterator using another iterator like that, I'm pretty sure you just "nest" the iterators, i.e. the first iterator will call next internally on the iterator you constructed it with, etc
that wouldn't improve perf any
it would make it worse
You also sacrifice insertion and deletion speed.
There's no "iterator nesting" happening here. The suggestion is to call the base class's __iter__ method to get an iterator, rather than calling the derived class's override of the __iter__ method.
because OrderedDict is a subclass of dict, it's legal to use the regular dict.__iter__ for one instead of OrderedDict.__iter__.
!e ```py
from collections import OrderedDict
d = OrderedDict(a=1, b=2, c=3)
d.move_to_end("a")
print(list(d))
print(list(dict.iter(d)))
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | ['b', 'c', 'a']
002 | ['a', 'b', 'c']
Oh yeah. insertion and deletion would be slower since it needs to deal with connecting nodes when it does that. That makes sense
Also yeah it definitely uses the regular dict iter when you use dict.__iter__. You can tell because of the order. It doesn’t reflect if you’ve been using move_to_end
yep, that's what I was demoing.
Yeah since it doesn’t move the keys/values, it just reconnects nodes
I don't know what you mean by "reconnects nodes" - a dict doesn't have nodes.
The nodes in the OrderedDict
aren't used at all when you use dict.__iter__
Or is that not the right term to use there?
Yeah
Yeah it just iterates through the consecutively filled array
yes.
but... bypassing a class's overridden methods by explicitly calling base class methods on the derived class instance feels very icky. You're sidestepping the class's public interface. That doesn't seem wise to me.
Is there another way to do this?
This doesn't seem like a thing you should do at all.
The class defines how it wants to be iterated; it seems unwise to sidestep that and iterate it an entirely different way.
Okay
!e For an example of why this is a bad idea:
from collections import OrderedDict
d = OrderedDict(a=1, b=2, c=3)
dict.pop(d, "c")
print(list(d))
@raven ridge :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 4, in <module>
003 | KeyError: 'c'
That's using the same trick as you're using, except instead of calling the base class __iter__ on the derived class instance, it's calling the base class pop on the derived class instance. And it leaves the derived class instance in an inconsistent state, where it thinks the key still exists, even though it doesn't.
Even if there's no iterator nesting, it could still be an adapter internally
TIL about functools.singledispatch which mimics function overloading functionality, any thoughts about it?
I've used it before, it's ok
Apparently only the first argument can be type hinted, so that's a bummer
I think I ended up dropping it though, I think I needed to have more control, or slightly different behavior
Well, doing multi argument overloading at runtime is a bit of a bummer too :-)
fair enough
I don't know what you mean by "it could still be an adapter" - it's just calling the superclass method. Are you suggesting that the superclass could detect when the object it's passed is an instance of a subclass, and perform subclass-specific behavior in that case? That's technically true, but superclasses aren't supposed to know about their subclasses, so that would be an absolutely insane design.
anyway, you can look through https://github.com/python/cpython/blob/main/Objects/dictobject.c#L3524 to see that's not the case.
Objects/dictobject.c line 3524
dictiter_new(PyDictObject *dict, PyTypeObject *itertype)```
There’s a node with a reference to the "c" string, but the reference was deleted from the dictionary itself, so it fails to find "c" in the dictionary?
yes
That makes sense
Lib/collections/__init__.py line 120
def __delitem__(self, key, dict_delitem=dict.__delitem__):```
the OrderedDict __delitem__ calls dict.__delitem__, but also does housekeeping on the linked list.
if you call the underlying dict.__delitem__ directly, then the housekeeping doesn't get done, and its linked list goes out of sync with the internal dict state.
okay, I follow you know, I didn't realize that ordereddict was subclassing dict
In CPython, don’t objects always have their memory freed immediately when their reference count is set to 0? I answered that on an exam from a couple weeks ago, and it got marked wrong. It said the right answer was “when an object’s reference count is 0, nothing references it”
iin CPython, when an object's reference count becomes 0, its finalizer runs, and then (as long as the finalizer doesn't create a new reference to it) the object is destroyed and its memory is freed, yes.
Ok, I’ll ask to be given points for that question
the exact wording used might matter a lot.
question:
What happens when an object's reference count is zero?
Options: A: The object is no longer referenced. B: The object is ready for memory allocation. C: The object is being referenced. D: The object will be deallocated from memory immediately.
It said the right answer was A.
well, depends on what you mean by "immediately"
immediately its finalizer is run, and as long as the finalizer doesn't create a new reference, then the object will be deallocated.
I guess immediately as in it doesn’t have to wait for some scheduled memory freeing thing to happen later
Like how Java does it or something like that. That’s what I was thinking of
that's true - but, because it can be resurrected by its finalizer, the deallocation isn't necessarily immediate
because in between the reference count dropping to 0 and the object being deallocated, the finalizer runs, and that can delay the deallocation indefinitely.
!e ```py
class C:
def del(self):
global b
b = self
a = C()
print(a)
del a
print(b)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | <__main__.C object at 0x7f0454320fd0>
002 | <__main__.C object at 0x7f0454320fd0>
the reference count drops to 0 in the del a line. Once it drops to 0, immediately the finalizer (__del__) runs. The finalizer creates a new reference to the object called b, and the object is not deallocated, even though its reference count did drop to 0.
your teacher will probably appreciate that example, at least 😄
Alright, I see what you mean. I think I’ll accept how that question was marked now
Maybe if it phrased it like “if the reference count reaches 0 and stays at 0”
you can ask the teacher why the answer is what it is, and that some people on the internet told you that both A and D are correct, and see what they say.
Note that even if you disable the GC, the finalizer still gets called and the object still gets deallocated.
!e ```py
import gc
gc.disable()
class C:
def del(self):
print("destroyed")
a = C()
print("created")
print("dropping reference")
del a
print("done dropping reference")
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
001 | created
002 | dropping reference
003 | destroyed
004 | done dropping reference
Yeah, I remember reading about that, it only uses the garbage collection cycle to deal with circular references
Even if this typically isn’t something that happens, I think it still makes it so the more correct answer is A
And plus maybe saying that the class is about CPython is wrong. It just doesn’t talk about different python implementations. So maybe it’s wrong to be CPython-centric
other Python implementations don't even necessarily have reference counts.
Except idk if it’s common for memory to not typically be freed immediately in languages that use reference counting
but yes, A is definitely the most correct answer - it's basically the definition of a reference count.
And if a language is using reference counting, would it ever delay memory freeing until later after the reference count reached and stayed at 0? Or would it never make sense to do that?
it would probably mark it unused immediately upon the reference count reaching 0. Otherwise it would need to keep tracking it in some form after that, and it would prefer to forget it as soon as it can.
Alright. But still, I’m going to accept that question as it was marked now. Thanks for the help
So how do stack, pushing, and popping work in terms of parsing? when parsing through tokenized code
Reply to me with pings on if you know cause I gotta head off to sleep but i'm kinda curious tbh, thanks!
What's the specification for the process through which unicode identifiers are normalized, e.g. stripping diacritics and splitting some ligatures?
ah, NFKC
Guys how can I connect a web dashboard with my bot
why would someone want an implicit namespace package rather than an explicit?
What's the context?
general, I'm not sure why one would want implicit rather than explicit. There are also some things like this https://github.com/adamchainz/flake8-no-pep420 that actively seek avoid implicit, so i was curious
If you mean implicit namespace packages, it allows other libraries to be imported from a namespace
Well, the main advantage is that it's then possible to have different parts of the package in different locations.
Explicit namespaces usually avoid sneaky errors and shadowing
For instance maybe you have a core package, then plugins which add themselves under the namespace.
If I had a library called grobble I could have an implicit namespace called grobble.extra
and then provide my own sub-package inside it
but then other library authors could also use grobble.extra as the location to import their own libraries
That said, I'd like to see implicit dotted imports, like Java (I think? Kotlin has that for sure). If you type os.environ.get, you don't have to import os because you start at the bottom of the import chain
Although I don't think it is feasible without breaking changes, due to how the import mechanism works
It would be a breaking change either way, actually
I think the flask.ext namespace is a namespace package if memory serves right
So other libraries than flask can use that namespace to act as the import location
Ah, apparently they deprecated this years ago
Is there some tutorial on how packages/namespace packages/whatever work in Python? I'm completely confused by the terminology
Namespace packages are explained in https://www.python.org/dev/peps/pep-0420/
is there some article that explains all of the current state of packaging?
Theres another page in the python docs too
Python has a terminology problem: a "package" in the strict python technical sense is not what most people think of as a "package"
So "how to package apps/libraries for distribution" and "what is a python package" aren't the same thing
also, pypi is the "package index" which is a different meaning also
The python packaging tutorial was pretty helpful iirc
The Python Packaging User Guide (PyPUG) is a collection of tutorials and guides for packaging Python software.
To answer the original question: a module is a namespace and it corresponds with a .py file
A package is a module that has a __path__ attribute and can contain other modules. It corresponds with a directory that has an __init__.py file.
A namespace package doesn't have the __init__.py and serves a different purpose (explained in the pep, im on mobile 😛 )
based
please stop
ok
its actually complete bullshit how hard python packaging and even just imports in general are
everything about python is so simple and easy other than that
i don't know, imports make a lot of sense
they do on a base level, until you get deeper. and maybe once you go even deeper they make sense again
and packaging/distribution is slowly getting less fucked
where's the point of depth when they don't make sense?
relative imports mostly and trying to work around your ide warnings even when the python code itself runs just fine
i think if you understand the search path that kind of all goes away, no?
can't account for IDE warnings though
the warnings are half of what makes it so hard
and sure, thats not python itself but if its vscode or pycharm or another major program we all use, lol
'clearly this import wont work it is warned, lets try other stuff'
5 hours later, ah that warned import was it after all
😛
oh , this doc @grave jolt https://docs.python.org/3/reference/import.html
lol i can't account for vs code being wack
pycharm mostly does the right thing although in general it's a very powerful tool that is not really beginner-friendly
i've definitely noticed a trend of people asking about IDE warnings without ever trying to run the code
all i know is personally, ive seen a lot of very strong programmers get held up and annoyed trying to import at times. for something as simple as an import its funny
it's almost like dynamically-typed languages aren't beginner friendly
heresy!
strong programmers coming from other languages, i could see struggling. most languages i think lack a clear, "outsider-readable" explanation of "how all this stuff fits together"
if anything, python has unusually good docs in this regard
how does ruby search for gems? how does maven work? good luck finding that info
Can't say I ever had problems with the ide not understanding relative imports and importing from packages, usually it's just a misconfigured project root
python is comparatively simple, i think:
- python itself has a default search path including various site-packages directories
- setuptools/flit/poetry extracts contents from a package archive (tarball, wheel, whatever) and dumps them in site-packages
- pip fetches the archive from pypi and installs dependencies
- venv creates a python executable that has all the right search paths set up internally for self-contained use
I've had a problem with PyCharm recently not getting it completely right with imports but it was a more complicated (nested) project structure
most programming languages don't even have a venv equivalent...
i have that situation at work (except its like 10+ apps and not just 2) @sacred tinsel , i have a separate pycharm project for each
it's not ideal
i'd really like to be able to configure different interpreters for different content roots, since each app has its own venv
not sure if that's possible in pycharm
do tell
let's go #editors-ides yea
Is the logic true?
I'm passing around a module, that has a class instantiated within it, and then accessing that class. I'm wondering if this is bad practice at all? The reason i'm wondering is that mypy gives error: Module has no attribute when it's doing mod.class_instantiated_within_module.value, not sure what to search for though
I'm just curious, why are you passing around a module?
module has metadata within it
might not be the best solution, it's the thing that's happening atm though 😅
Okay, but metadata is data ultimately, right, so to pass around data you'd typically use an instance of a class
Yes - i'm not sure what you mean here though - there's an instance of the class created within the module, which is then imported
and when you say "class instanted within it", you are basically saying that the module creates a global of some class?
I have something like:
# metadata.py
x = 1
y = 2
other = Other(x = x, y = y, ...)
along these lines, and then elsewhere I have
from ...metadata.data_id import metadata
this sort of pattern
I'm saying that usually (there are rare exceptions I'm sure), you don't "pass around" modules themselves, e.g. as arguments to functions. Typically you'd just pass around instances of objects, occasionally you'd pass around types.
Okay, sure, so you have a global
@halcyon trail makes sense, i guess i'll ignore all errors here then
Well, that wasn't what I was saying 🙂
Probably you should just be passing around the other instance itself
that's my solution 😎
for this it's probably not worth fixing - but instead can think of better approach in future if this is nonsense
but idk how you'd usually do it - if you have module level vars, and classes, then passing around a module kinda makes sense
Need a bit of a broader context to answer that question. Using globals isn't usually the best but if it's some kind of fixed, unchanging data then it's often fine
maybe it should be a class instead of a module, seems kinda semantics tho
why does it make sense to pass around the entire module
why doesn't it? It's a module that has metadata info, i don't understand why it wouldn't make sense
when you say "pass around", are you saying you have a function def foo(x): print(x.other) and you call it foo(metadata) ?
not saying my lack of understanding carries weight here - just saying that I don't really see why it would be an issue 🤔
yes - i have a module which imports the metadata, then passes it to another, which has functions which act on that metadata
what does "passes it to another" mean
passes it to a function?
because "another" there can only refer to "another module", and you don't "pass" things to modules
passes to a function , yes
# metadata/data_1/metadata.py
x = 1
other = Other( ... )
# mod1.py
from metadata.data_1 import metadata
from . import mod2
mod2.something(metadata = metadata)
something along these lines
if that's not clear it's probably not worth making clear tbh tho
it could be fine in rare cases. if you pass a module as an argument to a function, then the assumption is that you have other modules that have exactly the same interface, otherwise obviously there's no point making this an argument ot a function
But, the fact that these modules have the same interface isn't expressed
That's the point of classes and instances, when you write a class it expresses a certain interface, and now you know that every instance of the class has the same interface
In this case, it seems like you're just passing data around, the way you'd usually do that is to have a class that holds the data you want, and then passes instances of that class to functions
I have a module that has the data i want - and pass that around
i just don't get the difference here i guess
instead of doing that I'd wrap everything in the module in a class?
So Other is a class
You know that all instances of Other will have the same attributes
I know what a class is - i don't understand why there's a meaningful difference in use between things here, the metadata is metadata for a particular data set
if mod2.something takes an instance of Other, then it's clear what interface you're expecting
basically the suggestion seems to be that I would instead make a MetaData( ) class, and create an instance of that which has Other as a subclass or something?
iiuc
If your module has more data than Other, then yes
not a subclass
a member
@dataclass
class MetaData:
x: int
other: Other
or something like that
so I'd have MetaData with class vars which have the values which are currently globals within the metadata.py module 🤔
right fair, and if i have different vars for different data I'd have to add to this class it seems
which is fine i guess,
sorry @halcyon trail , i am wondering, given :
#metadata.py (old)
from . import project
x = 1
other = project.Other()
i can convert this to a class with:
# metadata.py (new)
class MetaData:
x : int
other = project.Other
metadata = MetaData(x = 1, other = project.Other() )
then, before I've been doing:
from .metadata.data_id import metadata
metadata.x
metadata.other.attribute
the usage now would be what 🤔
I'm not quite sure about the nesting levels here since you named both your file and your variable metadata
ah ok - can change them to make this clearer that's fine, sorry
that said, you wouldn't define MetaData in the same place where your global is defined
part of the whole point here is that you could define MetaData at a higher level, and then reuse MetaData class to define metadata instances in multiple files
defining that class ensures that you are defining all the metadata attributes you need
ok... i think i can just write from here, what you've said makes sense, and has been something i've intended to do, but think i'll just wax this and do that now. Thank you
np
!rule 6 @fathom snow, we don't allow any advertisements here.
has anyone used the real python membership? is it worth it?
O.o
I feel so directionless
Which is weird. I almost always have a sort of 'pull' that always keeps me moving forward
does anyone know why isinstance(np.array([1,2,3]), Sequence) is False?
it doesn't have .count, .index etc
i wasn't sure how that worked - is the presence of those "mixin" methods required?
https://github.com/python/cpython/blob/main/Lib/_collections_abc.py#L1015 Sequence also doesn't use __subclasshook__, i assumed it would use that and check for the presence of __getitem__ and __len__ the way Collection checks for __contains__ etc.
Lib/_collections_abc.py line 1015
class Sequence(Reversible, Collection):```
yes, it is implied that Sequence also has count and index. Typecheckers rely on this for example
https://github.com/numpy/numpy/issues/2776 discussion on this happens here
inheriting from Sequence should grant those methods perhaps, but they seem like odd requirements for the protocol
i guess it's just not a good fit for the type hierarchy envisioned in collections
pretty much
fortunately numpy as np.typing.ArrayLike now
a good point raised was also 0d arrays
0d arrays are cursed though
hyperopt uses them internally iirc
unfortunately ArrayLike isn't generic 😦
what's the right way to handle this
def get_label_mapping(data_labels: ArrayLike, given_labels: ArrayLike) -> Mapping[_S, _T]:
data_labels = np.asarray(data_labels)
given_labels = np.asarray(given_labels)
mypy correctly knows to specialize the type of data_labels, but it's still just np.ndarray, not np.ndarray[_S, DTypeOf_SWhateverThisIs]
maybe this is running into limits of what you can infer statically
huh, it looks like numpy.typing.NDArray doesn't actually exist
weird...
!e ```python
import numpy as np
print(np.array(10))
@paper echo :white_check_mark: Your eval job has completed with return code 0.
10
hmmmmmmmmmmmm
- return product(*map(enumerate, iterables))
+ return product(*map(enumerate[_T], iterables))
``` this fixed it
Isn't numpy working on getting type hints for size, shape and type for arrays ?
Or am I misremembering
type, yes, IIRC
but size/shape would mean dependent typing, which Python doesn't (really) support
just marking the size isn't really dependent typing
you can do it to some extend in normal Python, with Peano integers, and you can even to things like +1 or -1
I would settle for having to manually cast when changing sizes
Also I think annotating number of dimensions is more generally useful than annotating the specific shape
Again, I don't mind if I have to cast manually after adding a dimension
That said, i have messed with writing an NDArray interface in Idris
The ergonomics for the end-user are there, but there is a lot of burden on the library author to actually do all the dependent types correctly
what do you mean by marking the size?
and I tend to agree, that tracking rank is generally going to be more useful, and more doable, than tracking specific dimensions
although, broadcasting tends to be fairly magical, would be interesting to see whether and how that could be made to work
wait hold up how do you do Peano multiplication in a type system
In Python, you can't
you can't even do addition, really
you can do it I guess if you define all the types by hand
I dont know whether it has been discussed or not, or even it is relevant to this channel. But wanted to know your opinion about this repo
so, on which one would you agree. is there any popular / reliable site or repo you can share with me?
no, just talking from expperience
these lists are opinionated, so there'll always be disagreement
can you elaborate
anyone who thinks an exception is more readable than an if is completely out of their mind
i agree. but they tried to present something, which was needed. and as it is on github, i will request u and others to contribute and improve the lackings/mismatches
The example that they had provided in https://docs.quantifiedcode.com/python-anti-patterns/maintainability/returning_more_than_one_variable_type_from_function_call.html isn't exactly compelling. There's plenty of other cases where it makes more sense to return a None type than raise an exception.
If user input influences the result of the function whatsoever then it's only proper to raise a specialized exception, but if it's some get_cached_credentials method on some cache handler service object in the guts of your code, None makes sense.
Even then, in typed Python, one could argue that a Union of types is a distinct type itself, and that isinstance checks or (future) type guards are a way to refine that type into something specific.
this might sound dumb, but is there a way such that when you import a specific module, that modules modifies the current module that its being imported in first with the interpreter executing the code
an example is ```py
import preprocessor
#define PI 3.141
print(PI)
this mght be stupid
yeah , it makes sense .
I'm not sure how to work out which file imported the current one as if it is imported by many different files then it will just serve the cached one, but you can import __main__ and work on that ```py
file_1.py
import file_2
print(pi)
file_2.py
import main
main.pi = 3.14
Output
3.14```
you can then use inspect to read the source and do what you propose but idk about how you would do this for files that aren't __main__
but this would lead to issues if the file imported is itself being imported by another file that is being imported by yet another file
if that makes sense 😅
I don't think this is a good idea, I was just saying how to do it 😅
whats wrong with pi = 3.141?
i know, just messing around
that is objectively incorrect though. Checking if a file exists is meaningless, since by the time you use the information, the file could stop existing
im not going to use this in actual projects
cool idea tbh though, would be fun to mess around with
return value errors vs exceptions are a bit more debatable, but IO must always be try and see if it fails
macros bad is engraved into my mind
you could look through __main__ for all imports, then recursivly walk through each file that those files import until you hit a file with no imports, but thats just an idea, not sure how well that would actually work
errors are always better than bugs, so I don't really disagree with it, but it is by no means a hard rule, there are many cases where exceptions are just unwieldy
Hi, Why I am sometimes getting error with this
from .schemas import schema
and sometime with this
from schemas import schema```
you are running your program in 2 different ways
what command do you run to start the script?
uvicorn main:app --reload
I am running fastapi
I have developed so many project in django, but didn't receive any error like this , I run few project in fastapi too. but doesn't recieved this type of error
I am receiving it first time
essentially, the difference is that . imports require a parent package, so if you have a tree like
project root
\-main.py
\-package
\-a.py
\-b.py
```then in a.py, you can do `from . import b`, but you can't do `from .package import a` in main.py, you would have to do `from package import a`
My structure is as follows \-main.py \-models.py \-schemas.py \-settings.py
But still what is working currently is import settings in my models.py
from . import settings is giving an error
Yesterday, from . import settings was working
But , import settings was giving error
you probably changed how you are running your project, if you do uvicorn project_root.main:app, main now has a parent package, so . imports will work, and the path is one level up, so absolute imports will not
I've heard using Any is lazy, in type hinting, but I'm not sure how one would type hint this:
def f(
fn: Callable,
kwargs: dict[str, Any],
) -> Any:
return fn(**kwargs)
without using Any
you can use a typevar for the return value, but yeah, sometimes the type system just can't express it
not sure what the difference is here, isn't this Any a type var?
Any is just a type
ok hm, i'm not sure what this would look like with a typevar instead of a type then i guess
a TypeVar would look like
T = TypeVar('T')
def f(fn: Callable[..., T], kwargs: dict[str, Any]) -> T
oh ok, where do i find doc on this, and what's the advantage here?
https://mypy.readthedocs.io/en/stable/generics.html
essentially, it means that if the return type of fn isint, f(fn, ...) will be int, rather than Any
not sure what T is, but we're saying - we're passing some callable with variable amounts of T, and then we're returning T
it means, given a Callable return any specific type T, we return that type T
oh, Callable[ ..., T] means - variable amount of args, and return type T, ok cool
people said that the best way to learn code is doing some projects
but if i dont know how to code the projects is it okay to look at someone code tutorials (like how to make hangman game in python)
EAFP prevents TOC/TOU errors
Important for checking file existence in particular
Not important in all or even most applications, but I believe that is why it's encouraged
Oh lakmatiol already said it 😛
it's uncharitable of you to think that i meant catching exceptions is always bad, independent of context.
i disagree with with eafp as a philosophy
being trigger happy with try/excepts will bite a programmer in the ass a milliion times before they ever find thenselves with a race condition like this
I think EAFP doesn't mean 'exceptions'. For example, if open returned either a file handle or an error value, it would still be thread-safe.
Had the keyed indexing pep been approved, something I wanted to make was a type annotation system for pandas, but the more I learn about the library, the more futile such a thing sounds.
I understand numpy is doing something similar, but I don't think there's much you'd need to represent other than the data type of a given array.
I think it's pretty futile because most schemas in pandas only become known at runtime
and the point of type annotations is mostly to do checking statically
Perhaps, though, Python's typing system is what makes something as flexible as pandas a possibility. Is R typed?
R is dynamically typed
but it doesn't really matter, you can have dynamically typed things within a statically typed language
At the end of the day pandas' dtypes and schemas are practically a mini type system unto themselves
Where I work, for example, we have concepts that parallel pandas dataframes in C++ (with far less functionality of course), and it all works just fine despite C++ being statically typed
I think being able to annotate what columns, dtypes, and index levels you expect would be pretty useful
I guess me saying shape was poor choice
But if you're specially slicing out a column called x being able to tell if that column exists would be incredibly useful info to get from static analysis
What is "foo" in Python?
foo and bar are just placeholders used in various programming examples. They're not keywords or anything like that.
fair enough, although i think EAFP would make a lot more sense if you could control the origin of caught exceptions more easily
e.g. "i want to catch TypeError but only when some_package.foo raises it"
also for what it's worth python nowadays typically doesn't require much EAFP, you can ask getattr/.get/next to return a default value instead of raising an exception
class NullContext:
def __enter__(self):
return None
def __exit__(self, *args):
return
def open_safe(*args, **kwargs, on_failure=None):
try:
return open(*args, **kwargs)
except FileNotFoundError as exc:
if on_failure is not None:
on_failure(args, kwargs, exc)
return NullContext()
logger = logging.getLogger(__name__)
with open_safe('something.txt', on_failure=lambda _,_,exc: logger.exception(exc)) as fp:
if fp is None:
print('Oops, file not found!')
I don't think it was ever about requiring EAFP, just that it's the mentality of the language
i think what i'm saying is that most python devs don't really "live by" EAFP except where necessary for toc/tou issues
it's ugly and awkward and you mostly don't need to do it
idk a quick google search shows dozens of style guides, articles, etc recommending it
This is a language that uses exceptions to stop for loops, after all
https://www.geeksforgeeks.org/eafp-principle-in-python/this article specifically says EAFP is for safety against race conditions
i agree that it's silly to catch IndexError instead of just checking the list length
https://gist.github.com/cdgriffith/fa48d9b7032f848ddd5c37c3df35dbb7 although interestingly the performance overhead (in cpython) only shows up if you actually catch the exception, so EAFP can be faster if you need to do lots of lookups in a tight loop that might occasionally fail
basically an optimization
maybe that blog post says that's what EAFP is specifically for but if you read around broadly you'll see tons of places recommending EAFP more broadly than that
i believe you
I think use of .get/getattr etc is really dependent on what you intend to happen if something isn't found
the thing is that python doesn't have any error handling, or mechanisms to make transformations of data easier, outside of exceptions
so often the alternative to catching is worse
Here's a good example from a quick google
if text.isdigit():
num= int(text)
else:
num= None
IMHO, this is bad code
It's also flawed I was thinking of is_numeric
you're using two different functions here, and assuming that isdigit() true is good enough to guarantee that int doesn't throw
it's even possible that assumption is true, but I still think this is bad
the try-except version is better
It'd be true for isdecimal but I agree that catching fits more here
another example is trying to set something that is nested a few layers deep into a dict, if all the keys are present, else do nothing. It's a lot nicer to do this with exceptions rather than to keep nesting if ... in ... checks
Ah good, TIL 🙂
Personally I would prefer a result type, you could just write num = test.toInt().getOrDefault(0) or something like that, would be much nicer, but it's not the python way
or sorry, I guess getOrNone()
!e ```python
def with_handlers(*exc_handlers):
exc_types = tuple(t for t, _ in exc_handlers)
def do(func, *args, **kwargs):
try:
return func(*args, **kwargs)
except exc_types as exc:
for t, h in exc_handlers:
if isinstance(exc, t):
return h(func, args, kwargs, exc)
return do
def constant(val):
def func(*args, **kwargs):
return val
return func
text = 'hello'
print(with_handlers((ValueError, constant(None)))(int, text))
@paper echo :white_check_mark: Your eval job has completed with return code 0.
None
"we have composability at home"
so ugly
I'm glad that so many languages are now big on allowing left-right transformations of data, really makes a huge improvement to readability
it's only ugly if you use python and not hy 😛
what's a left-right transformation?
!e ```python
def with_handlers(*exc_handlers):
exc_types = tuple(t for t, _ in exc_handlers)
def do(func, *args, **kwargs):
try:
return func(*args, **kwargs)
except exc_types as exc:
for t, h in exc_handlers:
if isinstance(exc, t):
return do(h, func, args, kwargs, exc)
return do
def do_stuff():
yield 1
yield 2
return 'hello'
gen = do_stuff()
gen.send(None)
gen.send(None)
print(with_handlers(
(StopIteration, lambda f,a,k,e: int(e.value)),
(ValueError, lambda *args: print('that is not an integer')),
)(next, gen))
@paper echo :white_check_mark: Your eval job has completed with return code 0.
001 | that is not an integer
002 | None
is there a straightforward way to get the function that triggered an exception from its traceback?
I just mean that the data goes from left to right. Things are executed in the order you read them.
like what I wrote above
num = test.toInt().getOrNone()
I think that's the first reason why your version is hard to read. The second reason is because once exceptions are involved, you don't just get a value that you can act on, you need to pass lambdas in and catch stuff, etc
I'd rather start with a value and then call getOrThrow() if I need to
I feel like you (or somebody else?) has mentioned UFCS as well but it's a very rare feature
but yeah, pipe operator and extensions are probably the two most common ways to do it. And in lisps of course it's trivial to do with a macro.
But anyway, but given how python doesn't have any left-to-right support, it doesn't have any support for a Result type, it doesn't have null aware operators, etc... the alck of all these features ends up making exceptions a lot more appealing than they might be otherwise, which is what leads to EAFP, broadly
(I think)
i agree that the main limitation is syntax, not necessarily language semantics
(print (with-handlers ((StopIteration (fn [f a k e] (int (. e value))))
(ValueError (fn [f a k e]
(print "that is not an integer")
None)))
(next gen)))
a hypothetical hy interface to the same functionality might look like this, which i think is a lot more readable
with and try fundamentally are not composable, and lambda is very restrictive
you should see the codebase where i work. it's a pain i have to suffer every day.
handlers = [
(StopIteration, handle_stopiteration),
(ValueError, handle_bad_int),
]
with handling(*handlers):
next(gen)
@halcyon trail meanwhile this does not look bad to me
try:
... # 80 lines of complicated code with lots of i/o
except:
return None
like this?
once in a while we get help questions like this... "why doesn't my db insert work", "why doesn't my discord bot respond to messages"
If you use a bare except and return None, how will you ask forgiveness for what you've just done? 😛
handlers =
it's hypothetical, but could be easily adapted from the with_handlers that i wrote above
I'm also not really sure what the purpose is here, how we ended up with stop iteration
just demonstrating how you could theoretically make exception handling and EAFP style more composable and functional(-looking) without losing the good aspects of it
consider writing a function just to wrap something in try/except and return a "result" type. this is a generalization thereof
the question is what have you actually gained over try/except. I guess the overall thing is an expression, that's something
but when its' so ugly you have to factor out separate "handlers" variables, I don't think it's a win in any other way
but it's kind of a strange example because there isn't any compsition that I can see, I just see two separate handlers for the same input stream
being an expression means it's fundamentally composable, and now this chunk of handlers is something you can re-use
well, more composable than try/except
you could use it as a decorator too
i'm not arguing that you should all go start using this
what are the "good aspects" of exception handling/EAFP style?
avoiding the toc/tou problem
and generally interacting with external resources, where you don't have a cheap way to check if the resource is available until you try to use it
you don't need exceptions for that either though
right, you can return some kind of result type
and toc/tou is only relevant in rare cases
and you could use this with-handler pattern to wrap stuff that raises exceptions by returning a result type instead
your example of handlers above would be handled more nicely by sum types + pattern matching
Yeah, you could
but it's all kind of a workaround, the obvious thing is just to start with the result/sum types 🙂
absolutely
on sum types + pattern matching
It's much easier to start with a result type, and if you don't plan to deal with errors locally, .getOrThrow(), than to wrap exceptions back into results/values
good point, but it is interesting that python gives you just enough tools to bolt on that kind of functionality
hell, you could literally just return ValueError if you wanted
get_or_throw is then almost trivial, and 3.10 lets you pattern match instead of using if isinstance
yeah, will be interesting to see if/how pattern matching shakes things up, will there finally be a really widespread Result library in use, etc
I haven't had much time to think about it
wouldn't a "result" type basically be
Result = Exception | Any
well, maybe Result[T] = Exception | T. not sure how to write that properly in python
something like that, yeah, but realistically you'd probably want Result to be a proper class
so you can give it member functions
Any thoughts about these two repos? i found them from reddit.
although, I don't know if you can then match directly on a result, is there any kind of "operator overloading" for pattern matching? Probably not. So you'd have some kind of public attribute that you match on
class Result(Generic[T]):
data: T | Exception
etc
Also you probably also want at least the option of a Result type that is also typed on the kind of error
not to always erase it
i was about to say, you can get checked exceptions with this
@lilac yew nuitka has been around for a while, never used it though
some people on hacker news said that it was modestly faster than cpython and worked pretty well for distributing standalone binaries
Sometimes i think , isnt it possible to rewrite the python lang to run to complie in machine code. do you think the creator(Guido van Rossum) who said he gonna make it faster, is actually trying to convert it into machine code excutable?
If it is faster then cython then why it is not so popular? strange..
# Ad-hoc sentinel
class Nothing:
pass
nothing = Nothing()
E = TypeVar('E', bound=Exception)
T = TypeVar('T')
class Result(Generic[E, T]):
def __init__(self, value=nothing, exception=nothing):
self.value = value
self.exception = exception
unsure if there's a way to allow E to be a Union[Exception1, Exception2] , or if that "just works"
because speed != popular,
There are often many pros and cons to different setups, Nukita doesnt ship with Python by default it also has limitations but also errors can be more complicated and no everyone wants / needs a stand alone exe
isnt it possible to rewrite the python lang to run to complie in machine code
pypy and graalpython both do this, i believe. but with just-in-time compilation, not ahead-of-time
is actually trying to convert it into machine code excutable
unlikely, that'd require a bottom-up rewrite of cpython
cython
cython is not cpython. also library compatibility i think has been questionable in the past; not always clear what will and won't break with something like nuitka, even with the best intentions of the developer. and i think relatively few devs care about distributing self-contained python binaries, compared to people writing web server backends, command line tools, machine learning libraries, etc.
cython is actually a great example of what cf8 said: i usually see a 2x or more speed up by literally just copying and pasting my pure python code into cython. but do you want to do that all the time? definitely no.
it would however be really really cool to have multiple up-to-date well-maintained python implementations, not unlike common lisp. use cpython for dev and interactive stuff, compile with nuitka to ship to the end-user, or run on the server with pypy or graalpython.
but equally in the world of data science you cant really get much faster than what python already has in it's ecosystem
considering it's mostly written in highly optimised compiled languages
I mean, depends what you're talking about, but that's not exactly true
a + b + c in python, even if a, b, c are numpy objects and + goes straight to machine code
i agree it's not necessarily true. but more importantly data science work is heavily interactive. the ml/data engineers however could definitely benefit from having a faster python runtime when trying to make things go fast.
is still far less efficient than a + b + c in a compiled language, or probably even in julia
Thats what weld is for :P
even pypy has substantial function call overhead and doesn't appear to be that aggressive about inlining (in my limited testing)
weld?
it would however be really really cool to have multiple up-to-date well-maintained python implementations, not unlike common lisp. use cpython for dev and interactive stuff, compile with nuitka to ship to the end-user, or run on the server with pypy or graalpython.(edited)
Indeed, it would be though imagine the complexity behind it. Even though they would share some common aspects (e.g the standard library, or the basic reference algorithms for features) it is a really long/hard process to catch up with CPython. Also you have account for that, they will always have to follow one release back since even in betas a lot of internals might change.
it's a JIT compiler that links data science libraries to avoid callbacks to Python
I think in terms of the basic design of the language, if you were designing a data science language from scratch, doing what Julia did is simply the obvious thing to do
good point. that comes with the territory of python being a goddamn enormous language
I'm not sure where Julia is in terms of ecosystem though, other language decisions, etc
link? sounds like numexpr-everywhere
julia's big problems right now: sloooow jit warmup and a bad case of NIH syndrome when it comes to tooling
the former is actively WIP and has improved a lot
the latter, idk
Yeah, I've read a bit about problems in Julia
the basic premise though of using LLVM as a backend is somewhat hard to argue with though
at least, assuming the warmup issues can be overcome
ty, i will play with this
what's kind of interesting is whether you can build a nice language for data science that's statically typed or not, I'm not really sure, all the repl's for static languages I've used had some limitations, but maybe they can be overcome, I'm not sure
i think julia-the-language is wonderful, and the library ecosystem is growing very fast and iterating towards what i think is a viable python replacement for researchers. but there is no scikit-learn equivalent yet.
julia could be a good "general purpose" language too, at least from the perspective of its language design. not sure how the runtime does with high concurrency stuff like a webserver.
recently i saw some articles where they are claiming julia should be the language for writing quantum computing codes
One thing to just keep in mind is that, let alone the advanced ones you can't even do any of the fundamental compiler optimizations on the bytecode compilation step. The most you can do is just a bit of constant folding. For doing advanced stuff (e.g common subexpression elimination, loop invariants etc) you need to record traces in the runtime, with known types and codepaths and then you can do the optimizations.
Is it clear to anyone why this script hangs:
import subprocess
def main():
p = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write(b"echo cmd\n")
if p.stdout:
print(p.stdout.read())
print("done")
if __name__ == '__main__':
main()
I thought maybe because of buffering, but pasing bufsize to Popen doesn't help
If I eliminate the stdout=subprocess.PIPE argument, it runs as expected (and of course it will skip the loop since p.stdout will be None)
@halcyon trail Doesn't /bin/bash open a REPL? i.e. it asks for input lines repeatedly.
Yes, that's the issue
Not sure I follow, why does it hang on the stdout call as a result?
that makes sense, actually
that explains why it works when you stop capturing stdout
when you hit the end of the parent process, stdin closes
and then it probably flushes stdout at process end
oh, maybe it's stdin that needs to be flushed?
p.stdin.flush() doesn't work
nope
very strange
there should be some way, to keep a process alive, and send it stdin, and receive stdout
if you close stdin that way I don't think you can reopen it
Closing stdin will cause bash to exit
I'm confused as to why flush doesn't flush the stdin
It does, bash just doesn't exit
akarys@mojito ~> bash
[akarys@mojito ~]$ # I'll press CTRL+D to close stdin
[akarys@mojito ~]$
exit
akarys@mojito ~> ```
bash doesn't have to exit
I wouldn't care if the script still hung
but why does it hang before printing out cmd
that's what's confusing
well, I guess there's nowhere else for it to really hang 🙂
After you do p.stdin.write and p.stdin.flush, you would expect that there would be something available to read on stdout
okay, version that works
import subprocess
def main():
p = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0)
p.stdin.write(b"echo cmd\n")
p.stdin.write(b"echo cmd2\n")
p.stdin.flush()
if p.stdout:
for line in iter(p.stdout.readline, b''):
if line.startswith(b'cmd2'):
break
else:
print(line)
print("done")
if __name__ == '__main__':
main()
for the curious
There is something available to read, but read will read until EOF which you won't get. Usually you'd send something with newlines and then do readline
@halcyon trail there are a bunch of warnings in the docs about deadlocking due to reading and writing to a subprocess, i think they recommend using .communicate
but communicate waits until the process ends.
if you need to interleave reading and writing, you basically need to read and write in 2 different threads
fair. but in this case you're still waiting for stdin to be sent fully, then streaming the output. is that even guaranteed to work? like what if the program can't read from stdin until its output is sent or something?
i think i've encountered that before
you only have to use threads if you want to be writing at the same time as you're also reading. If you're fine with writing, then reading what's available up until either some kind of sentinel , or until a timeout
you don't need threads
but that is a way to do it, for sure
what i'm wondering is whether it's possible for the subprocess (in this case bash) to cause things to deadlock. is it possible that p.stdin.write could get stuck blocking forever for any reason?
my guess would be yess
if you keep writing in, but don't empty stdout
maybe the bash subprocess will stop, waiting for stdout to be empty'ed
but I'm not really sure
that was what i was wondering, i don't know either
I really need to read my copy of Linux Programming Interface
I've been putting this off for like, 5 years
if i really had to stream data between myself and a subprocess i'd probably want to use https://anyio.readthedocs.io/en/stable/subprocesses.html
thanks for the recommendation
graingert#9275 is a big anyio advocate, they hang out in #async-and-concurrency often
used to see them on freenode #python a lot as well, not sure if they moved to libera
there are also standard asyncio utilities for subprocesses with a similar interface
the reason i like anyio is because it has good support for structured concurrency w/ task groups
doing the same in asyncio can be obnoxious
Lets say, stripping all features like templates, views etc from Django and embedding DRF and optimising for fast API creation and deployment. But not losing compatibility with Django modules. An out of the box RESTful API Framework in Python. Any opinions?
just incase your interested: ```py
file_1.py
import preprocessor
import file_2
DEFINE PI 3.14
print(PI)
print(file_2.x)
file_2.py
import preprocessor
DEFINE x 10
DEFINE foo(x y) (x * y)
print(x)
print(foo((1, 2, 3), 2))
Output
(1, 2, 3, 1, 2, 3)
3.14
10```got it working by messing with imports using sys.meta_path then re-writing the files source code
hmm, just realised I'm missing a print, will need to look into that
nice
yo maybe not the best place to ask but not really sure where to haha
anyone here experienced security ppl that could assist with tracking illegal wildlife traders?
basically doxxing them to the police
We won't help you with doxxing, no matter the justification. That's a violation of both our rules and Discord's.
maybe thats not the right word..
it sounds like something that could just as easily be used maliciously as not, and we'd have no way of knowing how it's being used.
its not "exposing" anyone, its simply finding the info and passing it to the police
of how whats being used
right, the doxxing part is the finding the info in the first place. We won't help with that, because we can't know how the info would be used.
And doxxing bad people is still doxxing, and still against the rules.
the info would be shared with a conservation society in SEA as well as the police there
this is not a malicious endeavour, its one to try and tackle the rampant illegal wildlife trade that threatens many primates/other animals with extinction
and i told them i would see if i could find someone that may be able to assist
Sounds like a noble cause, but we still cannot help.
i understand the premise is against the server rules and it cant be discussed in here but maybe there is someone here with the knowledge that could assist me privately
!rule 5
This rule covers any practical discussion of projects that could be used maliciously. We also do not want to facilitate seeking private help for the same reasons.
5. Do not provide or request help on projects that may break laws, breach terms of services, or are malicious or inappropriate.
This conversation is also off-topic for this channel. If you have further questions regarding our rules please message @summer lichen.
i understand what youre saying, that the same knowledge can be used maliciously, but thats simply not the case here
its also separate from discord
!warn 239000912733929482 We have no way of verifying that, and won't be making an exception to the rules. As you've been told, if you want to discuss this further, send a DM to @summer lichen.
:incoming_envelope: :ok_hand: applied warning to @lime sky.
when you say "discuss this further" do you mean about the rule or about the question haha
but alright apologies
about the rule, and why we won't be bending it.
yes understood
i have a question
i want to make a password vault
project that stores all my passwords
would i need sqllite3 in order to store my passwords
im planning on using tkinter for gui
That's probably a question for #python-discussion, but yes, you'd need a database of some kind
anyone familiar w python webscraping?
Ja, just ask your question
Why does __exit__ take 3 parameters: exc_type, exc_inst, exc_tb, when it could easily just work with the exception instance, from which we can get the class jut by doing exc_type.__class__ or the traceback with using traceback stdlib package. Is there a reason why this was done?
I've wondered that before too
I believe that's just the usual way to represent an exception
but why is that? if we don't need those attributes why force them onto us, it just results in having unused attributes for no reason
exception is represented well enough just by the actual exception instance, I don't see any need for the other params
it might be a historical leftover from when strings could be raised, and were not objects.
hm, I wonder why that wasn't removed in py3
I don't think you could raise strings in first python 3 versions
I'd also guess that it predates the traceback module by quite a bit so the traceback was useful.
Some things just aren't worth the hassle of changing
I could be wrong about the reason
The historical explanation occured to me as well. And maybe traceback was added later as a module
That could be verified easily
I think someone recently said how to get un-instantiated instance methods from super(), I can't find it
cuz super().__class__ gives you the super class
is it possible? I'm trying to write a fix for Pillow so I can just use Image.Image but if, for some reason, the inheritance chain gets messed with it'd be nice if it automatically worked anyway
Awesome. Finishing reading head first book about Programming Patterns.
This book is indeed... worthy of thousands books. Amount of brain-friendly new... levels of programming philosophies is overwhelming
https://www.amazon.com/Head-First-Design-Patterns-Brain-Friendly/dp/0596007124
https://www.youtube.com/watch?v=hGIW2fDb0jg
Head First Design Patterns: A Brain-Friendly Guide [Eric Freeman, Bert Bates, Kathy Sierra, Elisabeth Robson] on Amazon.com. FREE shipping on qualifying offers. Head First Design Patterns: A Brain-Friendly Guide
Focus & Concentration
(Without Vocals)
📌 SHORT DESCRIPTION
So here we are, one bigger mix. :)
As I said in this mix are only few songs new.. this mix is compilation of the best focus songs. I removed one more aggressive or distracting songs and added some new. So hope you will enjoy it. I also make some really cool visuals for video to have bet...
that book's about Java...
who cares? Patterns are universal for any language.
A small translation from Java to Python is easy to make.
disagree
whether a particular pattern is useful or idiomatic will depend on the language
don't you go to in built into python patterns
yes, there are super specific to language
that said
shrugs. in general they are applicable to most of languages anyway
small correction to consider current language can be done too)
I don’t think the fact that it’s a Java book disqualifies it
the brain-friendliness makes it worthy to learn even you are pythonist
after all, there is no equivalent book in python about it
oh
it’s not just about Python, either
you should probably read the channel description
I wonder why it wasn’t named “implementation-discussion” or something like that
We've iterated through some names, advanced discussion seems to be the best option so we've sticked to it
It's not just about the implementation, it's also about advanced concepts, such as metaclasses, for example, so it's difficult to pick an exact name
dm @summer lichen instead of pinging the admins
@unkempt rock As Cookie says, send a DM to @summer lichen if you believe there's some action that the staff should take. Don't bring up personal grievances in public channels, and especially not in on-topic channels.
i know i've ranted about it before, and people are sick of hearing about it, but: there's no reason to use the famous Singleton pattern in Python.
@spark magnet let's hear the hot take.
As I see it, if you need to make sure that a class only has one instance and provide a global access point to that instance Singleton is the right way to go.
consider that modules already do that exact thing
- I think it is very rare that a class by its nature needs to have only one instance. It's usually a characteristic of how your program uses the class
- it's easier by far to simply make one instance and access that global
And in many cases you could just use the module itself and some functions.
- classes that can only be instantiated once make it very hard to write isolated unit tests, so people build yet more hackery to get around the singleton-ness
Some design patterns just deal with limitations of the languages in which they evolved
I don't really buy the "universality" principle of all design principles
@spark magnet
Thanks for breaking your points down
- Let's try to narrow the scope a bit;
Let's say that we want to implement a RESTful API.
We have a few internal requirements:- It's going to talk to a database when it's running, but we want to be able to decouple thay layer with an in memory data structure to have fast unit tests while developing.
- We want to keep our "routes" very thin, and instead have the logic in some domain service class. This class is then instansiated with a
SomeDomainNameQueriesclass that can handle the different data queries we want to be able to handle (and that class then depends on the actual data model (fx. an ORM).
We don't want to instantiate this Service class in every route where we need it with a concrete SomeDomainNameQueries class, so we instead make a service container.
This service container class is then responsible for returning a concrete instance of the Service class that the different routes can use via dependency injection.
Now this concrete service class, we only really want one instance of that, so here to me a singleton pattern makes sense.
We could then in our test mock the ServiceContainer class to create the different instances of the services with a SomeDomainNameQueries class that could implement the different query operations and save them to a dict or w/e datastructe that makes sense.
i'm wondering about a lot of this design. Why do you want to have only one instance of the concrete service class?
Yeah that makes sense, I am however still naive and on the "universality" team :D
I think 'the gang of four' doesn't buy into universality either
This class is then instantiated with a
SomeDomainNameQueriesclass that can handle the different data queries we want to be able to handle
well, then you can just pass theSomeDomainNameQueriesas an argument, right?
Sorry for the rambling 😆
I could have many instances of a service class, the program would still work, but I don't need that.
Since during runtime I would always want to instantiate the service with the same type of data layer (I don't want to mix and match between fx a database and a file)
Sure I could do that, but then my router needs to know the concrete instance of the SomeDomainNameQueries which is a no-no in my book
@austere spruce you say "i don't need that", but what's the harm in instantiating the concrete service class many times? Do you need it to be a singleton? Why enforce that?
to me it shows design intent, and I guess it's also faster.
i was afraid you were going to say faster 🙂
haha
creating a global variable will give even faster access, and it doesn't hide your intent of making a global variable
to me it was just the: "As soon as I have create one of these things, I always want to create them with the same arguments".
so I only really need one, so why not just make it a singleton.
Just make one, assign it to a global. Then in your tests you can make more of them.
or, make it the right way each time you need it.
Maybe I am reading into this wrong, but it seems like you don't like the singleton pattern? Or is it merely "I don't think it's a clear way of doing things, and you can do it in these other ways which I think is more clear"
Sure, then I would just have to mock "patch" each of the variables in my tests.
You can also expect an object of some shape, like in classic dependency injection. For example (pseudocode):
class InMemoryDatabase:
def __init__(self, pictures):
self._pictures = pictures
def find_picture(self, id):
return self._pictures.get(id)
class PostgresDatabase:
def __init__(self, connection):
self._pool = PostgresPool(connection)
def find_picture(self, id):
with self._pool.acquire() as conn:
cursor = conn.execute("SELECT (name, url) from PICTURES WHERE id=%s", (id,))
row = cursor.fecthone()
if row is None:
return None
return Picture(id=id, name=row["name"], url=row["url"])
def make_routes(db):
return <something>
and then pass the 'production' instance at your entry point and pass the 'testing' instance in your tests
but I know that Python developers are usually allergic to this type of thing
The problems that Singleton solves can be solved in simpler ways in Python.
yeah that's what I am doing in my tests normally :-)
albeit I have an extra layer for this SomeNameQueries so I don't need to implement all ORM methods
(and btw, sometimes they aren't even problems)
@grave jolt
I would then have
class DatabaseUserQueries(UserQueries):
...
and then In my test:
class TestUserQueries(UserQueries):
...
Fair enough, I'll think a bit more about it 🙂
@austere spruce sometimes what's going on is that people know that globals are bad, so they don't like the idea of putting this into a module: the_thing = Thing(). But a singleton is a global, just dressed up in fancy clothes.
Good point, the only difference here is that instead of class is responsible for only having one instance of itself it's now the caller that's responsible of it. I am not saying that's inherently a bad thing, just something to keep in mind.
Right, but often it's the caller's concern that says there should be only one anyway. and if you put the_thng = Thing() in thing.py, then Thing is still saying, "here's the one to use if you want to use The One"
and if you find you need your tests to do something tricky like patch, that's a clear sign that the class wasn't by its nature a singleton.
yes for sure, often that should be the callers choice, but in cases where it shouldn't be (to show intent of use) then it could potentially be a good idea to do it the other way.
An example of a global variable that's not necessarily a singleton is asyncio's event loop. Sure, at any single point there can only be one event loop running. But you can set a different one (like uvloop), or stop and garbage-collect the current one and create a new one
That wasn't in the case of singleton, it was a response to the suggestion: why not just have module variables where the concrete service classes are already instantiated.
I think there's plenty of those examples, maybe we strayed a bit too far away of the discussion though which was the claim that (I paraphrase) "Singletons are never a good idea in Python".
In any case, time to go outside and enjoy the weather, thanks for the discussion! Have a good one
sounds terrible
Yeah it was 24C at 8 when I woke up, absolute hell. I went to where I work to stay there instead since they have AC 
@grave jolt what does f"{x!s}" do?
{x} uses the .__format__ dunder, !r makes it use .__repr__, and !s makes it use .__str__
But surely that doesn't join them?
actually, it's already faster with just an f-string, but !s reduces a little bit of overhead because __format__ accepts two arguments
hm?
It won't be like 0, 1, 4, 9, 16
You can do
", ".join([f"{x!s}" for x in xs])
!e py xs = [0,1,4,9,16] print(", ".join(f"{x!s}" for x in xs))
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
0, 1, 4, 9, 16
@lunar trail :white_check_mark: Your eval job has completed with return code 0.
0, 1, 4, 9, 16
f"{x!s}" it does the same thing as str(x), but faster 🙂
That's because join in CPython first makes it into an array of objects anyway.
Huh
I was surprised as well 🤷
Seems like a weird decision but fair enough
What about list(gen) vs [x for x in gen]
list(f"{x!s}" for x in ...)
I'd expect list(gen) to be slower
!e
This is how it can leak into Python:
def foo():
for i in ["not strings:", 1, 2, 3, 4]:
print("sending", i)
yield i
print(" ".join(foo()))
@grave jolt :x: Your eval job has completed with return code 1.
001 | sending not strings:
002 | sending 1
003 | sending 2
004 | sending 3
005 | sending 4
006 | Traceback (most recent call last):
007 | File "<string>", line 6, in <module>
008 | TypeError: sequence item 1: expected str instance, int found
first the generator runs until the end, and only then join checks if it resulted in strings.
doesn't f"{x}" call .__str__ by default?
!e
class Foo:
def __format__(self, format_string):
return "quack, but also " + format_string
def __str__(self):
return "meow"
print(f"{Foo()}")
print(f"{Foo():aaa}")
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
001 | quack, but also
002 | quack, but also aaa
When an object doesn't have a __format__ method, {x} falls back to __str__, and if it doesn't have a __str__, it falls back to __repr__.
ah i see
I looked into this, and remember reading that it was done as the iterator needed to be iterated over twice (so it could work out how much space to allocate for the string or something, idk), although I don't think that would explain why the same thing would apply to things like sum, i.e. sum(i for i in range(10000)) is slower than sum([i for i in range(10000)]), I tried to look at the source code and I couldn't see anywhere that the generator was being turned into an array (although granted I didn't really know what I was looking at). I sort of came to the conclusion that generators were just... slower, because they're python constructs rather than c constructs (for lack of a better way of saying that, because I don't really know what I mean). Any ideas if i'm misunderstanding something, or am I along the right lines...
it could work out how much space to allocate for the string
Well, CPython doesn't seem to do that, because it first exhausts the iterator, and only then checks if any of the elements are not strings
With sum it doesn't seem all that clear, it depends on the input size.
oh, hm, yeah, list comp only seems to be faster for small input sizes from what I can tell. I guess that's just because the list needs to be reallocated as it grows, although with small inputs there's a fairly significant difference, so I guess that could be due to generators being slightly slower to iterate over, which makes sense.
This is where I read that from, fwiw https://stackoverflow.com/questions/9060653/list-comprehension-without-in-python#comment11376919_9061024
You could just be seeing the generator iteration overhead on lower input sizes for the sum
Yeah, maybe the allocation time starts being an issue only in larger list sizes.
Hey @static bluff!
Uh-oh! It looks like your message got zapped by our spam filter. We currently don't allow .txt attachments, so here are some tips to help you travel safely:
• If you attempted to send a message longer than 2000 characters, try shortening your message to fit within the character limit or use a pasting service (see below)
• If you tried to show someone your code, you can use codeblocks
(run !code-blocks in #bot-commands for more information) or use a pasting service like:
I know its hard to tell without context, but does this make sense?
Feel free to ask any questions, of course
Tbh it only makes any sense at all because I know your weird naming conventions
(Joking)
For real, the notes and docstrings are VERY helpful
The if not inside the while loop is weird
That might never trigger?
😄

