#internals-and-peps
1 messages · Page 101 of 1
!e
from dataclasses import dataclass
@dataclass
class Coord:
x: float
y: float
print(Coord("a", None))
@wide shuttle :white_check_mark: Your eval job has completed with return code 0.
Coord(x='a', y=None)
Although type checkers like mypy and pyright are very helpful
I heavily don't. Runtime exceptions and poor editor support drive me insane.
unless using an assertion package like pydantic
pydantic doesn't (generally) do strict type checks and it happily converts some compatible types as long as the final value turns out as specified
At least not with the default nonstrict fields
>>> import pydantic
>>> class MyModel(pydantic.BaseModel):
... my_attribute: frozenset
>>> MyModel(my_attribute=["a", "b", "c"]) # pass in a list
MyModel(my_attribute=frozenset({'a', 'c', 'b'})) # gets converted to frozenset
I even miss C# at this point for excellent language support in VS
IntelliJ just randomly dies on me with an Analyzing loop I can't reproduce and vscode requires loads of configuration every time I set it up since you can't use environment variables in its config reliably
I make pretty heavy use of validator decorators
I wish they would integrate iterable and dict unpacking to dataclasses
how so?
Like if I had a dataclass that I wanted to turn dump as kwargs into a function I could do **dataclass_instance or as positional args *dataclass_instance
Idk how the kwargs one works
It requires keys im pretty sure
It would just be a really cool exception for dataclasses
Imo
I thought you meant the other way around - unpacking a tuple and having it turn into a data class
It does require keys and __getitem__
hm, do isinstance checks work off the inheritance of a class, or its implemented protocols?
It uses the types by default but is customizable
Why not both!
It uses the inheritance hierarchy by default, but a metaclass can override that and do other stuff.
I'm trying to scrap 83 endpoints an hour, which takes roughly .02 seconds per endpoint, all can be completed within a minute. I want to do this faster, should I look into Cython for this or is that overkill?
My current setup is using a multi-threaded loop that calls each realm as they reset.
Hi guys I’m getting a pc and I have some questions can anyone help
Hello, this channel is for discussing Python itself from a higher-level and more abstract perspective:
Discussion on the use cases, implementation and future of the Python programming language including PEPs, advanced language concepts, new releases, the standard library, and the overall design of the language.
For non-Python questions, we have several channels available in the Off-topic / General section, the topmost of which is #ot0-psvm’s-eternal-disapproval.
hi
👋
I want to draw a 3D shape and then project it into the image plane. At the moment, I am using cv2 but I can only draw very trivial wireframes (project endpoints of a shape and then draw a line between them on the opencv image)
is there an opengl-style way to draw stuff in python 3.8?
I tried using opengl but it doesn't seem to work for python 3.8
More context: I have parameters for a 3D ellipsoid and I want to generate it and display it on an image. My idea was to generate the 3D shape itself in the world coordinate frame and then use the camera matrix (which is available to me), to project that 3D ellipsoid onto the image
This is what I am drawing using opencv right now
But, ideally, this is what I want
The green lines you see in the first image represent the axes of the ellipsoids that you see in the bottom image
The bottom image is from the mobile app where the ellipsoids are being generated using opengl and arcore
I want to do the same thing on my computer using the geometric parameters of the ellipsoids. Is something like that possible in Python 3.8?
if im understanding correctly, your question simply boils down to, can i draw random ellipses on an image/frame in python
and once phrased that way, the answer should be simple. yeah why not
hm, anyone know why pylance wouldn't type hint on Type[int]?
it's weird, using pydantic's conint/constr gives me no argument completion, but if I wrap it in a generic, like Optional[conint suddenly I get assists
I'm not sure what part would be confusing the editor
and whether it's fixable within python's constraints
Can you show an example?
like, reproducible code sample
import typing
import pydantic
class T(pydantic.BaseModel):
a: pydantic.constr( # no completions
b: typing.Optional[pydantic.conint( #completions
this is on vscode w/ python+pylance LSP
@desert peak hmmm, I see. Perhaps you should file an issue on the Pyright repo?
oh I don't get illegal annotation
Well, Pylance thinks that a call expression is illegal as an annotation, it seems. That's why it's not completing.
Does from __future__ import annotations make any difference?
that's kind of upsetting how weak the type ecosystem in python is even after all the effort expended on it so far
well, type checkers have bugs and issues, yes
I have filed 15 issues on the pyright repo so far
its essentially the issue of annotations are not meant purely for type hints, but type checkers don't do a very good job upholding that idea
I missed that you said "pyright" above instead of "pylance"
ah
well, pylance uses pyright for typechecking (in a weird relationship because pyright is opensourced and pylance is not), so behaviour present in one is probably present in another
Isn't that what Annotated is for?
but yeah, it's very new
even so, it's better than Jedi
seems like pydantic will respect typing.Annotated
In [5]: class A(pydantic.BaseModel):
...: a: typing.Annotated[str, pydantic.constr()]
...:
In [7]: A(a="hello")
Out[7]: A(a='hello')
In [8]: A(a=3124)
Out[8]: A(a='3124')
yeah, but Annotated only exists since 3.9
yeah, was about to say
Oh wait, typing_extensions has it: https://github.com/python/typing/blob/master/typing_extensions/README.rst
interesting
does annotated solve the problem I'm seeing? I'm on 37 but typing_extensions probably already exists in my deps tree
it would allow you to specify the pydantic annotation as well as a type hint
Does anyone know of a project on GitHub which implements multiprocessing.Pool (with q input and q output) cleanly?
Every worker in the Pool would have to check the q and have an exit condition, but I'm struggling to write in a way to avoid the code duplication. I've achieved it by passing the actual function to another one which helps avoid duplication but seems rather messy.
I just spoke to my ducks and they suggested using decorators. Gonna look into it.
@vital lake this sounds like a question for #async-and-concurrency
has anyone thought about potentially trying to make Python's Virtual Machine in hardware?
like some chips can interpret java-bytecode https://en.wikipedia.org/wiki/Java_processor
A Java processor is the implementation of the Java virtual machine (JVM) in hardware. In other words, the Java bytecode that makes up the instruction set of the abstract machine becomes the instruction set of a concrete machine. These are the most popular form of a high-level language computer architecture today.
python bytecode seems too high level for a hardware level impl
guys
for business uses?
i need help. everyone is ignoring me when i ask.
well
this is a channel for discussion of the language
it could be that your question is not posed in a way that is easy to read/answer
or that nobody knows how to help you
all i said was "hey can someone help with my coding"
i just joined the server im sorry if this is the wrong place :( i just need help
try #❓|how-to-get-help (and post your actual problem)
not neccesarily, I was thinking maybe you could get raw python bytecode, write it to some sort of memory and then the chip could interpret it. Sort of like micropython but on a chip implimentation...
sorry, I mean to ask
like something that is actually viable for use in the real world?
it probably wont work but maybe
like clear efficiency gains
its unlikely but if you could code for a micro-controller in python and it can interpret python bytecode as well as a C compiler can compile for arduino or something
then maybe it could be efficient
but I thought this was pretty cool
yeah thats what I was possibly thinking about
like if you could somehow implement a stack machine in hardware, like FPGA, it might be possible to interpret python on a hardware level
how would you impl the entire object model with just hardware though
thats the issue
like dunders and stuff
It occurs to me that you can't do set Cartesian product with the * operator, though I don't know that that would be possible since you can't have look-ahead
@worn lantern Can you change your name to be easier to read? ASCII characters are preferred. Our nickname policy is given in #rules
am I wrong 😉
I'm not even sure that I know what lua is so I can't tell you
its an awful language that I hate
You are free to have that opinion.
in lua you have to declare if a var is local instead of indicating if its global (python)
and you have to type end at the end of a block of code (instead of using indentation like a sane person would like python)
and other illogical things that really tick me off
My position is that if your code block is too long for you to easily see where it started, having a delimiter like end or } isn't going to give you any information that whitespace doesn't.
Exactly
@worn lantern about python bytecode: it changes from version to version, which is another difference from Java bytecode.
The way that java compiles to byptecode is part of the spec because of the jvm, yes?
yeah thats another problem
cries in basically every other language
Is there a recommended way to have a shared importable object in python?
I need to be able to reuse an instance of a class in various other classes as a parent
Make it a module global object in one module, and from module import obj to import it into others
Does it have to be marked global? What do you mean by module global object?
Just an object at the top level of a module. Defined outside any class or function.
I'm just curious how this works. So if I define an object at the top of module, then import it in various files, the same object will be available everywhere? Does python "re-run" the module code each time import is done or does it "run" it once?
A module only gets run once, unless you do something tricky to cause it to be run more than once
So, every time you import a module, you get the same module object, and its attributes - the global variables of that module - are the same.
Very interesting, so this is fundamentally different from how for example include would work in PHP
Yeah, Python doesn't have any easy way to do a literal include. Instead, import finds the code for a module, runs it, bundles the results into a module object, saves that object into sys.modules, and returns it to you.
The next time the module gets imported, the copy saved in sys.modules gets reused.
Lua is superior in embeds
Much more
You can't even fathom how much it's better for poor avr cpus
I have some datapoints say x, y, err_y and want to integrate these points, I mean I want to generate table as x, int(1/y) and err_int(1/y). Could anyone suggest me any suggestions or python example or statistics tools?
hi can i ask for help here?
Hey! The places you can ask for help are #python-discussion, the TOPICAL CHAT/HELP channels, or the main help channels (see #❓|how-to-get-help).
@rich cradle hi i need help with running files at the same time #help-burrito
ok 😔
Is there a dunder method for collection[key_or_index] += value or does it just call get item, add, set item?
It calls getitem iadd setitem afaik
its certainly not in logic.
why define everything as local? just go with global instead
also just use indentation!
if lua did that, as well as making 0 false and 1 true, I might actually like it but I dont because it doesnt
(in lua 0 and "" is true. because scew you)
it sacrifices useability for speed
embeds like microcontrollers?
Could be. Or really small AVR systems
thats a really specific need..
I mean
most of embeds are avr
if they are not arm then they are avr and you better bet that you want to save cycles/mem
Well industry doesn't know fun
sadly enough
They will either force you into smallc/asm and in better cases lua
When it comes to avr
I'd prefer smallc anyday tbh
agree
how much ASM do you know?
A bit, not so crazy amount to call me robot
aarch64, Z80, x86_64 and really bare minimum of avr
"not so crazy" huh haha
I mean
oh I'm also getting into the gameboys z80 8080 merge thing
I don't remember on top of my head instructions like 4-leftbitshiftxor
their names are so long lmao
me neither, I always have the instructions infront of me haha
I mean most used stuff + SIMD are easy to remember
but for example this
CVTTPS2DQ
Like bruh
mega bruh
"Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Signed Doubleword Integer Values"
😩
Gotta love CISC in it's extremes
Yes it's really nice
are you aware of http://copy.sh/v86/
Run KolibriOS, Linux or Windows 98 in your browser
Its very useful for working on stuff like MikesOS
which is an OS in x86 assembly, its cool to mess around with
btw whats your opinion on micro-python?
micro python sounds nice
I think it could be very good in embeds as well
Mhm you're right
My friend tries to implement ISA that would natively take python bytecode
thats what I came on this channel to talk about haha
from here
it might be a processor doing microcode and a large cache for the stacks
problem is, python byte code changes often :/
well, there is no standard python bytecode, unlike JVM bytecode
ima go because I just realised we just over took a channel so I'm heading back to python general
people have recreated windows in the browser
its quite surreal, using a browser to emulate an entire operating system which has a linux kernel and gui stack and stuff, only to open a browser inside that and serf
!e ```py
import dis
def f(x, y):
return x[y]
def g(x, y):
return x.getitem(y)
dis.dis(f)
print()
dis.dis(g)```
You are not allowed to use that command here. Please use the #bot-commands channel instead.
Why do these two functions need to not compile the same way?
I suppose your question is more about why dunders are looked up on the class and not on the instance
Someone mentioned that using the operator looks it up from the class instead of the instance, but he said he wasn’t completely sure if there was a really good reason for that
Yeah
Well if you're using the item access syntax python can be sure of some thing it can't be with the getitem attr: it knows the amount of args it needs, and that the method needs to be looked up on the type. With the getitem attr it doesn't know that you are looking up getitem, so it does a normal method attribute access and then a call
Wouldn’t you always define it with only self and other? It seems like it doesn’t work otherwise
Thanks, will ask there
you could define it like this py class Foo: def __getitem__(self, other, third=None): pass
But it reads it as a tuple if you try to give multiple arguments
When using the operator
exactly, that third argument can only be used if __getitem__ is called directly
Oh, yeah I get what you mean
its not great practice to do that, but its not expressly disallowed
When you use the method directly,it might as well be your own method with 20 params, python won't differentiate it or it'd have to special case all of the methods and possibly break other things
So it would be too complicated to make it behave in a special way like that for dunder methods? So it just doesn’t treat them any differently?
I think it's more a matter of it not being worth it, not being too complicated
So like they could do it, but it wouldn’t really accomplish anything?
I don't see why it wouldn't be possible, but I doubt the improvements would be big enough to matter compared to the bloat it'd add
No, it's actually different, because x[foo] is not the same as x.__getitem__("foo") (because it's looked up on the type, not the instance)
same for other dunders
Nothing's preventing you for defining an instance attribute with the same name as a dunder for example, and there's no way the compiler would know about it, so you'd have to account for everything like that and probably end up with something similar to LOAD_METHOD and CALL_METHOD
You could still probably do some optimizations like locking in the signature if it isn't an instance attr etc. but by that point the interpreter probably did enough checks that it's a negligible improvements.
I don't think anyone would really mind if the method dunders were reserved to only be methods on the types, but they aren't intended to be called directly in the first place as the special syntax or buitlins are there for it, making this fairly useless
I'm sure the reason is "because it's faster"
That limitation cuts the number of lookups in half.
That’s the reason for why the operator looks it up from the class, right?
Right
i think there is another reason, but it's escaping me.
And also: how would it work for __getattribute__ if it looked it up on the instance?
It would look __getattribute__ up on the instance, whereupon the instance's __getattribute__ would need to be invoked to find that attribute, so it would look __getattribute__ up on the instance...
But regardless: if dunder lookups were changed to look up the name on the instance first, and fall back to the type, every Python program would run slower. Looking things up in 2 hash tables is slower than 1.
And it's impossible to change getattr(inst, name) to begin returning getattr(type(inst), name) - that would obviously be a backwards incompatible change, even if you checked if name was a dunder.
It would mean it's possible to set the attribute on an instance, but not to get it.
So it doesn’t look it up from the instance no matter what because that would make using operators slower, and it doesn’t look it up from the class no matter what because that would ruin getattr?
Seems like it to me, yeah.
If I open an instance of a python interpreter with subprocess, can I read its memory and potentially dump its call stack?
trying to achieve a portable solution that doesn't require modification of the script that is running.
you just broke me
I started following the chain...
why do you need to read the memory and get the stack?
trying to get a listing of every function call and the state of the call stack at that point
though I realize that the better way to handle that is probably within the script, using decorators
Or using sys.settrace
👍
I didn't know about this! Thank you!
the trace module seems to be little-known
ooh...
this is very interesting...
very interesting...
One of these days I need to just read through all the builtin modules
@heady mauve btw, writing your own trace function isn't hard if it comes to that.
it looks pretty easy
even if it doesn't fit the end goal I still plan to mess around with it
oh sys.settrace is AMAZING
indeed 🙂
someone should make an awesome tool using sys.settrace
Maybe one day
seems like it'd be useful
you mean like a debugger, or a coverage tool? 🙂
please stop
a coverage is cool, now with timing inside we might get a profiler ... but im not usind python for speed ....
There are already nice Python profilers, like Py-Spy and PyInstrument
Hi everybody. I am a novice to ML and I decided to play with PCA and PLS. I collected a NIR spectroscopic dataset for three different samples of batteries, used in the cars. I've already applied PCA on it using matlab, but now I want to use PLS regression from Sickit_learn on the same data. I've searched online and found out that I'd need predictor and response variables, but I don't know how to choose them from my dataset. Does anyone of you guys have some experience working on PLS? Please help me figure this out. I've been stuck on this for days.
🤔 🤔 🤔
Is there anywhere in cpython that uses abort() to raise the abort signal todo with memory?
Hoping there is otherwise im magically currupting memory out of nowhere and being aborted 
is your python code the only thing that magically corrupts memory?
Well i believe its pytgon freaking out because rust is dropping something python still wants
However trying to work out what exactly is causing it is 
crazy
i'd like to learn to profile my code properly, i've no idea where to find out what things are taking what time 🤔
You can look into the cprofile tool
cprofile is the most common and it's built into the stdlib
replace insulting word with "Rust"
@vocal sinew this video isn't on-topic for this channel. I can't really tell if it's advertising a specific website or giving general advice, but the latter is appropriate only for #career-advice.
after further investigation it does seem that Python really wants to access data that it shouldnt even know about so gonna be fun time debugging if it isnt todo with a discovered socket error
one thing I miss from powershell: being able to have a switch that evaluates expressions for each arm
oh yikes. time for less python
Its pretty much entirely a native rust lib
does anyone know whether the new match statement will be able to evaluate multiple regex against a string, for example?
#justpowershellthings
switch -Regex ($target) {
'^(etc*)' { $Matches }
'(?<group>okay)' { $Matches['group'] }
default { '' }
}
after not writing powershell for a long while now, that -Regex looks so funky
but I miss it
Nice
Can you use sys.settrace to only invoke within calls to functions of certain files?
Is it possible to draw a 3d shape on an image using matplotlib3d?
I know we can do it for 2d, but I am trying to do it for 3d but can't figure it out
I am looking for something like this: https://stackoverflow.com/a/15592168
real_object.__dict__items() ^ copied_real_object.__dict__.items()
returns set() because is no difference
real_object is copied_real_object
False
real_object == copied_real_object
False <=== Why
shouldn't they be equal since the __dict__ is the same?
unless an object overrides ==, it does the same thing is does
dataclasses, enums and namedtuples get a sensible == implementation for free
anyone have any idea about my problem?
ah, ok. thanks @flat gazelle
@unkempt rock you may want to ask in #data-science-and-ml instead
you would have to implement that filtering in your trace function, but the trace function can return None, meaning, don't trace code in this frame any more.
coverage.py does this.
Hi, Where can i get help for developing website crawler in Python?
!site rules 5
5. Do not provide or request help on projects that may break laws, breach terms of services, be considered malicious or inappropriate. Do not help with ongoing exams. Do not provide or request solutions for graded assignments, although general guidance is okay.
I don't think that's something we can help with, though in general, refer to #❓|how-to-get-help.
what is the most efficient way to approach reversing encrypted values for begginers
Is there a reason to use one of these approaches over the other?
# Approach 1 - using *args as function parameter
# ****************************************************************************
def gas(a, b, *rho):
z = a + b
rhoco, rhoco2, rhoh2o = rho
print('z\t', z)
print('rhoco\t', rhoco)
print('rhoco2\t', rhoco2)
print('rhoh2o\t', rhoh2o)
rhox = ([0.1, 0.2, 0.3], [9, 8, 7], [3, 4, 5])
gas(4, 5, *rhox)
# Approach 2 - using tuple as function parameter
# ****************************************************************************
def gas2(a, b, rhox):
z = a + b
rhoco, rhoco2, rhoh2o = rhox
print('z\t', z)
print('rhoco\t', rhoco)
print('rhoco2\t', rhoco2)
print('rhoh2o\t', rhoh2o)
rhox2 = ([0.1, 0.2, 0.3], [9, 8, 7], [3, 4, 5])
gas2(4, 5, rhox2)
It really depends on the use case. If you already have packed things up (just like in this example), it makes more sense to just take it in that way (and this is also more explicit).
though without PEP 3113 it would have been just def gas(a, b, (rhoco, rhoco2, rhoh2o))
(2.7<=)
that sounds highly malicious
by using the key
yes. *rho will take any number of values, and all the extras will get stored in rhoh2o
in your unpacking
@spice pecan :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | ValueError: too many values to unpack (expected 3)
!e
def fn(a, *b):
d, e, f = b
return f
fn('k', *['a', 'b', 'c', 'd'])
You are not allowed to use that command here. Please use the #bot-commands channel instead.
😐
hm, you're right. I'm thinking about a, b, *c = d
This would be a topic for #cybersecurity and not for this channel. However encrypted data is often encrypted for privacy and we're not going to help anyone violate that.
There is no way to efficiently break encryptions. Otherwise, there would be no point to encryption.
except for exploited, out-of-use encryptions
that's just the result of brute force decryption over time, yes? So, incredibly inefficient.
not necessarily. sometimes things were security by obscurity and weren't actually secure in the first place (or secure enough for their application)
Or common implementations of the algorithm were found to have a flaw that made them far less secure than they should have been.
[gRPC]
I'm sending python dict with some user data to server, I'll convert the request to json and then save on the server.
but first, is there a tool to check the validity of gRPC request before sending from the client?
Something is wrong here. I can't find out what is
Why not send the json?
what do you mean exactly?
You are doing a network request with gRPC right?
Why can't you just parse it to json on the server, then send that
ok, so..
I have multiple json files with array of users
I need to send those users one by one and then save them on the server (kinda merging)
I wrote a generator to (client)
loop all json files
loop users
yield user
then I take that user and sent it to server stub.sendUserInfo(UserRequest(user))
then on the server side, I'll take this request and merge them
Does anyone know where to get help with ipython or prompt_toolkit ?
!code
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.
You can use the !eval command in #bot-commands
writing grammars is boring; I need to make it more interesting.
Has anyone got python working in a RISC-V environment?
when should i use NewType over just aliasing?
also how can i make a generic NewType for matrix. I tried this but mypy complains that the type isnt bound.
T = TypeVar('T')
A = TypeVar('A')
Matrix = NewType('Matrix', List[List[T]])
please ping or reply on response.
and is there any overhead associuated with NewType?
@tropic belfry source: https://docs.python.org/3/library/typing.html?highlight=typing newtype#newtype
NewType is for defining subtypes of another type. See the example in the link. From the same link, the overhead is a function call, nothing more.
In your case, just do Matrix = List[List[T]].
thanks. it was annyoing to write out matrix when declaring just a simple list
also note that you can just use list instead of typing.List in Python 3.9+
no problem, it is technically deprecated in 3.9 (informally, there's no DeprecationWarning as the expectation is on type checkers to enforce the warning), but you don't have to worry until 5 years after the release of 3.9, where it will be removed
@last pollen wait so the typing module will be depreciated? And will there be a typing replacement?
not the typing module, only standard collection generic type hints: https://www.python.org/dev/peps/pep-0585/#implementation
the full list is in the link, deprecation strategy is here:
Importing those from typing is deprecated. Due to PEP 563 and the intention to minimize the runtime impact of typing, this deprecation will not generate DeprecationWarnings. Instead, type checkers may warn about such deprecated usage when the target version of the checked program is signalled to be Python 3.9 or newer. It's recommended to allow for those warnings to be silenced on a project-wide basis.
The deprecated functionality will be removed from the typing module in the first Python version released 5 years after the release of Python 3.9.0.
@last pollen want to see my cool way of rotating a matrix?
sure
not bad, it only works on square matrices from the look of it?
nope rectangles too
I might be looking at the wrong function
I'm on mobile so I'll check it out later
is storing the matrix column major intentional?
lol im not sure but it works.... I store all my matrixes row major and for rot90 just make a matrix that has the reverse for columns and rows. and i do a little bit of index trickery.
output[j][i] = matrix[-(i + 1)][j]
is this the line your talking about?
@last pollen ^
i might not know what row major means might mean the opposite of what i mean lol
rows = len(matrix[0])
columns = len(matrix)
yep thats intentional
i understand it might seem backwards but it works out like that
I see, interesting
thats clever @tropic belfry i only rotate 2d lists counter clockwise
but i loose the inner lists as they become tuples
list(zip(*grid[::-1]))
i just do this
thanks im surprised with the result didnt think itd work
def rot90_ccw(grid):
return list(zip(*grid[::-1]))
i also normally add a step keyword
so i can do 2 or 3 steps
i dont even know what zip does or ::-1
ah ok i see why thats helpfull here
its using slicing
def rot90_ccw(grid, step=1):
for _ in range(step % 4):
grid = list(zip(*grid[::-1]))
return grid
so it would look something like this
nice
there is some more things you can add as well
def rot90_ccw(grid, step=1):
for _ in range(step % 4):
grid = list(zip(*grid[::-1]))
return [list(row) for row in grid]
sorry if im not chattable im just tired ive been up all day working on tetris
no worries 😄
this will just make it a list of lists again
this is more or less how i do it
and i thought mine was compact
yours save memory, i have to create all the lists to tuples for then to convert them back to lists
embrace the immutable world. make everything tuples.
we haskell now
we sort in place here, sir
Does interpreter or compiler perform close() on the file object after reading content when I do something lika that? :
old_cont = open('extract.txt', 'r').readlines()
Its more handy than typical with loop, but I wonder if its idiomatic thing to do
IIRC no sorta; refer to Numerlor's comment bellow, it just ditches the file handle and hopes everything will be okay. if you want it todo something like that you want to use a context manager.
Yes, objects handling external resources like that are expected to clean up after themselves as a part of their destructor. But that destructor is not guaranteed to be ran
In CPython in particular, that will immediately get cleaned up. There's only a single reference to the open file, and when that reference is lost __del__ immediately runs and the file is closed.
But, that's an implementation detail of CPython. The Python language does not guarantee that behavior.
What are the semantics of __del__ then? a method that may or may not be called? 😄
like, technically a valid Python implementation might never call __del__, right?
Hm. Maybe. It's certainly not required that __del__ be called for objects that are still alive when the script ends. It's probably not required that it be called for objects that have already died when the script ends.
The one place it may need to do it is the case where the user explicitly calls gc.collect(), I guess
https://docs.python.org/3/reference/datamodel.html#object.__del__ - __del__ has a lot of caveats.
Hmm, I may need to fix something tomorrow morning 😬
anyone who knows how to make gui with qtdesigner and use it in a python program dm me need help, might pay
A module that may contain other modules, technically.
🤔
is a directory a module?
if i can do from x import y, does that mean x was / is a package?
If you can import from it, yes. It's a module if it's on sys.path
ok, kinda abstract, makes sense that it would be tho
Not necessarily. You can do from x import y if x.py contains a global variable y
Isn't this what we talked about before? It will be more interesting to start with a subset of the language, and do syntax and semantics, than to write the entire syntax out first.
!eval
You are not allowed to use that command here. Please use the #bot-commands channel instead.
the easiest way is inheriting from type and changing the methods you need changed
ah ok, what methods does type have
class METACLASS_BOI(type):
def ????????????????????????????????
__new__ which constructs the instance itself
__prepare__ which I will link in a bit
__instancecheck__ which lets you define how isinstance(obj, instance_of_your_meta) behaves
as well as allowing you to setup properties as class attributes.
hm alright
@finite pier why do you want to make a metaclass?
Why would you even want to do a class?
classes can be useful 🙂
I've found some applications of meta programming at work.
Essentially I had a class creation logic that I wanted to abstract out to use across multiple classes. Metaprogramming filled that hole perfectly.
Django does an excellent job of demonstrating alot of stuff like that as well if you ever feel like exploring the beast 😅
@novel vector The main rationale for classes is the "class invariant"; look it up.
semantics?
no, syntax.
Classes in python are useless, even in c you can do most of cpp things with structs, the only exception i can imagine is some huge framework like django, but I still hate how those classes are unclear and un-dry and non-kiss-able
If your point is that you can technically do whatever you'd like in the language without defining a class I'd agree with you, but I'm not sure.
Classes in python are useless
I wouldn't even know where to start if I wanted to replaced, say, widgets, in some gui framework with lots of inheritable behaviors --- what are you going to do: dispatch dicts and chainmaps?
Well good thing is to avoid explicit inherits and stuff like that, good example of nice design is rails framework, good example of bad design is django in which everything inherits from everything and you are being completely overloaded with crap
a lot easier to do:
class MyButton(Button, MyButtonBehavior1, MyButtonBehavior2):
...
with no other work
OK, you were saying it was boring to do just syntax! 🙂
@novel vector "classes in python are useless": everything can be done in assembly with no data structures at all if you want to take that argument far enough.
Guys, I did like 15 classes in cpp, something about 1500 in python, 0 in java, and I still would rather make project with java or cpp classes than python, idk for me its terrible
class fields are unclear, counterintuitive
I have never executed it xD
Compiling error, eclipse my love
But still, i do understsand java classes better than python ones
what makes Java classes better than Python classes?
Clarity, not repeating self everywhere
i have never heard of an argument where java was more clear before, well done
in Java, names could be locals or fields, isn't that confusing?
in python, init can be silently overloaded, and it is even worse
no idea if this argument / position makes sense, but i have tended to avoid using python classes as much as possible
My dude
most of what i do is relating to data, cleaning/processing etc - so i'm not sure if that factors into it ( probably ), i'm not doing gui's or whatever
the main reason that I've used a class is to gather some data, and mainly so i can do data.thing instead of data['thing'] in a dict
I couldn't imagine making some big game without classes, but python aint for making games
yeah, but you aren't making an argument based on language features, you're making one based on the fact that you wouldn't make a game with python
there are reasons for explicit self
i've never written a class that's made things clearer / easier to follow, which is more than likely on me. Just haven't found I needed one, although i've used them here and there as i mentioned
I mean its obvious, I did work in gamedev as tester and never heard of using python, same old same old, cpp, c#, lua, sometimes java, getting job in gamedev with python is like impossible
as for “clarity” - could you elaborate please?
yes, but that is entirely irrelevant to this argument-- which is why you think java classes are better than python classes
I feel like the repeating of self is such a nonsensical reason to hate oop in python that I find it hard to take the comment seriously
sometimes it gets a little annoying, but it makes sense logic wise
^
Any good article on using super() is everything I hate about python classes, and doing oop without classes is not impossible
...so what’s your criticism exactly
I don’t get it still
Yeah like ?
I mean is passing around structs with function pointers, such as in C, really clearer?
class Test:
def __init__(self, x, y, z, debug=False):
self.x = 6
self.y = 16
self.mult = x * y
self.z = 128
@classmethod
def d_print(cls, *kwargs):
if debug: print(*kwargs)
class FinalTest(Test):
def __init():
Test.__init__().super()
Simple class that already is r@ping my mind with this init() and super() and everything, this is sick that classes in python which is scripting language needs more lines of code than cpp which is supposed to be a low level lang
and __init__
Yeah thats my point, I can't even remember this crap
Always end up overloading some init or super
so you don't want to try to learn the language?
Can anyone remember every detail of the language at any given time?
that sounds like its on you
@novel vector maybe you could express your critique without sexual violence analogies? 😦
I code in py like 3 yrs, i did months on classes, I know I wont ever learn it
I don't feel like it is my fault cause I do understand other lang classes without any effort
That saying, practice makes perfect, is wrong. Practice makes mediocre
Yeah, but theory itself makes nothing at all
Hm. The problem that super() exists to solve is a problem in every OOP language. The "diamond inheritance problem". Python's solution to it is cleaner and more obvious than most other languages', I'd say.
this is like something you could easily pick up in 3 months...
Ah, I see. You don't know Python OOP. Carry on. 🤷
but well
I also find super() confusing and unintuitive lol
I don't think anyone here is going to convince you otherwise? and it's not like we have a stake in this, so...just use Python/other languages how you see fit?
But it sunk in after a week
Yeah, and after not doing if for one month I will forget it again, been there done that, classes should be intuitive to help you and not counterintuitive to kill your project before you even start
The only real problem with super() is that the name makes you think it behaves like super in other OOP languages, when it doesn't. It accesses the next class in the MRO, which isn't necessarily a parent class. But again: that's a tidy solution to diamond inheritance, and other languages have much worse solutions to it (C++'s in particular is... ugly. And still requires cooperation amongst all the classes involved.)
Usually when a language is called uninituitive, they mean, "it's different than my preferred language"
they are intuitive IMO
and Django wasn't hard to learn
I have seen so many context for super() usage in python, idk how im supposed to remember this
super().foo looks up the attribute "foo" on the next class in the instance's MRO after the current class. That's it - just one sentence.
What confused me, and still does, is that you don't have to pass anything to it, just merely use it within a method of the class. For the record, Ive only ever programmed in python and C
@novel vector what exactly do you find confusing about super() ?
The implicitness of it, is what throws me off
yeah - super has a zero argument form and a two argument form. The zero argument form is magical, and uses tricks to behave like the two argument form under the covers.
I mean once it sunk in, it's really nice but it took far longer for me to grasp it than I would have liked
Even in tutorials it is pain to read sometimes
for you, yes
that doesn't describe everyone's experience
the behavior is just one sentence. It finds the class in the MRO after the class in which the call to super() is located, and looks up an attribute on that class.
class Square(Rectangle):
def __init__(self, length):
super().__init__(length, length)
class Cube(Square):
def surface_area(self):
face_area = super().area()
return face_area * 6
def volume(self):
face_area = super().area()
return face_area * self.length
Overused, unclear, and its just some very basic example
you know super isn't necessary here right
at least, for Cube
but
okay this will be my last reply
I find it pretty clear
so shrugs
if you don't like explicit self you can just write a metaclass to fill it in for you!
lol
class Square(Rectangle):
def __init__(self, length):
super(Square, self).__init__(length, length)
Another great line, always have to think about it to understand it correctly
In python 3, it's just super() with no args.
and, this is bad OOP design, in general. It does not make sense for Square to inherit from Rectangle, because rectangles will almost certainly support operations that don't make sense on squares. Like, set width.
super is actually amazing! This when doing say chains of dispatching between observers, super calls makes everything work brilliantly
I think python oop just gives too much freedom, you can write bad oop all day and it works
In java/cpp you got pretty clear guidelines to follow or the code is not working
There's a whole lot more ways to shoot yourself in the foot in C++ than in Python. Like inheriting from a class with a non-virtual destructor.
Agreed, but not in classes specifically
that... is classes specifically.
Why is that? Never had any problems with classes in cpp
Slicing, for another example of a way to shoot yourself in the foot with classes in C++.
I was told to avoid this and so I did, I don't even understand that issue tbh
Same with pointers
I don't see how?
All squares are rectangles but not all rectangles are squares
In the geometric definition
you can set width of a square --- it will be the same as setting the height
the geometric definition doesn't mesh nicely with software design principles.
This is actually a pretty classic example of something that people design wrong in OOP all the time.
I'm failing to see a method a rectangle would have that doesn't apply to a square lol
you're writing in C++, but don't use pointers?
class Rectangle:
def set_width(self, new_width):
...
def set_height(self, new_height):
...
class Square(Rectangle):
...
s = Square(10)
s.set_width(20) # what should this do??
This is the guideline for modern cpp for many reasons
Avoiding bare pointers, sure. Not smart pointers.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def set_width(self, width):
self.width = width
class Square(Rectangle):
def __init__(self, width):
super().__init__(width, width)
def set_width(self, width):
self.height = self.width = width
Id imagine you would overwrite the width and height properties in square, but then inherit all the area calculating and the like from a rectangle
In manim, this makes a 20x10 square
🙂
Well, it's pretty surprising that setting the width also sets the height, isn't it?
not if it's a square
it just doesn't make sense to set just the width on a square
Why?
If you do that, you've violated the expectations of your users. For instance:
def double_area(r: Rectangle) -> None:
old_area = r.area()
r.set_width(r.get_width() * 2)
assert r.area() == old_area * 2
you can add a new method set_side if you think it's less confusing
class Room {
public:
double length;
double breadth;
double height;
double calculateArea(){
return length * breadth;
}
double calculateVolume(){
return length * breadth * height;
}
};
Just look how clear it looks without this ugly self everywhere, so beautiful ❤️
brackets are 🤮
This would work for rectangles, but not for squares.
@novel vector if you don't mind me asking, why are you in the Python discord?
I love python, I just hate python classes
double_area also sounds like a crap method on a rectangle
why would you have a double_area method lol --- it would also be rewritten for squares anyway
Double it, in which dim?
that wasn't a method on a rectangle, it's a free function written by a user of the Rectangle class.
This will not be true either: ```py
r: Rectangle
r.set_width(a)
r.set_height(b)
same as
r.set_height(b)
r.set_width(a)
which is a more realistic expectation IMO
True
yeah, that's a better example.
Well, of course it depends on what the public contract of Rectangle is. If it promises absolutely nothing, fine, you can spawn flying monkeys on set_width. But sometimes there are natural expectations
might be better not to subclass Rectangle and just have a is_square property tbh
then you don't have to worry
That's my thinking
The point is, if you make Square derive from Rectangle, you have to limit the operations supported by Rectangle - you'll never be able to add an operation to Rectangle that does not make sense when applied to Square, or users of Square will violate Liskov substitutability whenever they attempt to use those methods.
but i don't see much wrong with subclassing either
Honestly they should just be seperate classes, with maybe a mixin class related to 4 sided polygons because the more I think about, if square inherits from rectangle it is either going to be overwriting a lot
doesn't rectangle inherit from parallelogram
What does it inherit from it?
which inherits from polygon
a parallelogram might have a skew method
Yeah
maybe they're immutable and skew returns new ones
in that case, yes, you could make a skewed method that returns a parallelogram
Classes or instances
instances, yes
A lot of problems go away if they're immutable, sure. But it's still a classic example of an OOP design trap. If you make a Square subclass that derives from a Rectangle subclass, it limits the operations that your Rectangle can support.
It's almost certainly the wrong thing to do, because of that.
which operations does it limit?
I agree more now
So it depends how you define the square
I think glaz was saying the idea if there being a separate height and width, which is what would happen if you inherited from rectangle, is weird
All the ones we've just been talking about. You can't support "set width" and "set height" with sane semantics, for instance. Pretty much every mutator.
i wrote a sane set_width method
Imo a square would just have a side
well, set_width and set_height (or with_width/height) will just return new rectangles
but
it creates a weird ambiguity when you can have a 20x20 Rectangle which is not a Square
Can we agree that this is a sane function to use on mutable rectangles, which will fail when applied to mutable squares derived from rectangles?
def set_width_and_height(r: Rectangle, w: int, h: int) -> None:
r.set_width(w)
r.set_height(h)
assert r.get_width() == w
assert r.get_height() == h
Yes, that's sane.
but we're talking about immutable rectangles now
it will fail, but it's still sane to use the other set_width method
liskov isn't end-all, be-all
I think it's fine for a 20x20 rectangle to exist
Bc rectangles are a super set of squares lol
def set_width_and_height(r: Rectangle, w: int, h: int) -> None:
r2 = r.with_width(w).with_height(h)
assert r.width == w
assert r.height == h
``` This will work with immutable `Square` inheriting from immutable `Rectangle`
My example isn't a method. It's a free function written by a user of the class. The user wrote this method before Square was ever created, they performed operations on a Rectangle that appear to be sane. And if you later add a Square subclass that behaves as you propose, it breaks that user's code - the user's code stops working on all rectangles.
then don't use it on squares?
but it says it supports it.
Honestly, I don't see how making a separate Square subclass is useful in any way
Liskov really is the be-all, end-all of OOP. Code begins to fail in remarkably spectacular ways when you start violating Liskov.
that's the only time code becomes interesting
the type hint for set_width_and_height says that it supports any Rectangle. And it used to, until someone made a subclass of Rectangle called Square that violates the contract of a Rectangle.
it didn't violate the contract
you purposely grouped the asserts together to make it fail
sure - it violated the contract by making a method change something that it used to not change.
def set_width_and_height(r: Rectangle, w: int, h: int) -> None:
r.set_width(w)
assert r.get_width() == w
r.set_height(h)
assert r.get_height() == h
now it works
the function worked on all rectangles, until someone created a type of rectangle that it cannot work on.
it's the person who subclassed Rectangle who was wrong.
not the person who used it and expected its contract to be maintained.
there was nothing in the contract that said changing the width would not change the height as well unless you wrote it in there, and then you don't subclass
you wrote a function under a bad assumption
invariants that used to hold for all Rectangles cease to hold when applied to Squares.
Which is why Squares should not be Rectangles.
squares are rectangles
in geometry, yes. In OOP, definitely not.
@raven ridge How do you know what invariants Rectangles promise to hold?
I don't know what to say here beyond that it's literally a textbook example of incorrect OOP design.
def f(r: Rectangle):
assert type(r) is Rectangle
``` for example, this is true on bare `Rectangle`s, but fails on subclasses
being pythonic is for nerds
or e.g.
def f(r: Rectangle):
assert not hasattr(r, "color")
That's a really odd argument to make. That argument devolves to "there are no contracts, and any method of the class can behave however it wants"
I think you want to visit #esoteric-python
ah, thank you
have you heard of our lord and savior regex
Any method can behave however it wants? If the doc string of the method says """This will only set the width and never change the height""" then sure depend on that
yes and im ass at it
also idk how it would be really used here
otherwise, don't
cuz i need to parse stuff into a bunch of nested lists
if, after a method has been called, you know absolutely nothing about the state of the instance, then - what's the point of having classes, or methods, or anything?
if you know absolutely nothing about the state, then read the docs or look at the code
i don't know what to tell you
in my example, you did look at the code. You saw that set_width sets the width, and set_height sets the height.
then someone adds a subclass later where the old behavior stops holding, and set_width sets both the width and the height, as does set_height.
yes, and after you set_width you can assert that the width is changed
and after you set_height you can assert that the height is changed
but if you group your asserts you've made a subtle, but wrong assumption
wait do large organizations rlly have their python codebases have a similar structure as java does
you're technically correct, of course. Calling set_width might delete every file on your computer after it sets the width. As long as it doesn't say it won't in a docstring, then it's not out of contract for it to behave that way. But no user would ever expect it to, and a user would be entirely within their rights to complain if a subclass did behave that way.
i thought python was above explicit simple setter and getter methods
It is; we're talking about OOP in general, not Pythonic OOP in particular.
@grizzled spire definitely it's unusual to have getters and setters like Java
properties would be the idiomatic approach
i mean, i'm not a real programmer, so you know, you can just not agree with me
im getting flashbacks to java, where everything from the ground to the stars has it's own personalized methods to change and read the variable
right, don't do it in python
being a fake programmer has its perks
honestly idk why they do it in java
just allow the occasional variable to just be a public variable
why is that a problem
the idea is that if you want additional functionality upon reading/writing, it's easier if you already have getters/setters
it's just an Enterprise Thing (tm)
So, the docs say that set_width sets the width, and set_height sets the height. You read the docs, and the code, and see that's what happens. You write a function that takes a rectangle, sets its width and height, and then asserts its area is what it's expected to be. The tests all pass, the new function ships, you forget about it. Next year, someone introduces a Square that subclasses Rectangle, they update the Rectangle docs to say that set_width sets the width and maybe the height, and set_height sets the height and maybe the width, and then they make set_width and set_height on a Square both set both width and height. Now your function, written the year before, has ceased to be correct, despite it following the contract that existed at the time when it was written.
And, meanwhile, Rectangle now has a meaningless contract that makes it impossible for anyone to write any non-trivial code that uses it, because it's impossible to guess what the state of the object will be after any mutation.
the Rectangle contract didn't change --- it still does what it said
it said that set_width changes only the width, and set_height changes only the height.
someone came along later and updated it to say that set_width changes the width and maybe the height, and set_height changes the height and maybe the width.
did it say only
for the sake of argument, let's say "yes"
because if it says only then you need to rethink the subclassing of Rectangle
exactly.
that's on the subclasser
yes.
but if it didn't say only, then you can subclass, no worries
even if it doesn't say "only" - it's still on the subclasser, because it still breaks user expectations.
i don't think so, i'm pretty sure i know what to expect from a square
in a way that makes it impossible to write any generic code that uses that class.
your function doesn't take a square, it takes a rectangle.
this i disagree, my functions work on both
and that rectangle is a misbehaving rectangle - you set its width, and its height, and after that it should have a particular area, and it doesn't.
i can write functions that don't work on both if i tried too
i mean, if you expect width * height to be the area, but Rectangle inherited from parallelogram, your function would crash again, unless height meant the distance from lower line to upper line and not the length of the other sides
it really depends on what kind of geometry you intend to be doing
yes, it would be wrong for Rectangle to inherit from Parallelogram, for all the reasons I've been talking about.
Parallelograms support operations that do not make sense to apply to rectangles.
i don't think so, it really depends on what you want
if your instances are immutable, seems fine
hey guys is it possible to use .isdigit() to return something that isnt a bool
for example, if I enter a string 'fart'.isdigit, can I have it return the value -1 instead of it returning the value false
without using a try/except solution
just realized I made this post in advanced discussion im so sorry
that doesnt seem like an advanced question
!e For a somewhat advanced answer, you could do ```py
print('foo'.isdigit() or -1)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
-1
or in Python returns the first object if it's truthy, otherwise it returns the second object.
Does or work like a ternary operator in JS?
that's if
JS: condition ? trueValue : falseValue
Python: true_value if condition else false_value
or works like || in JS 🙂
the key is that True or loop_forever() doesn't crash
!e print(True or (raise ValueError("lmao"))
You are not allowed to use that command here. Please use the #bot-commands channel instead.
How does and function in this regard
the opposite
first if falsey, else second
!e
print(0 and 2)
print(1 and 2)
@gleaming rover :white_check_mark: Your eval job has completed with return code 0.
001 | 0
002 | 2
so if I reduce on a list of objects then and would return the last truthy object?
i always found it weird that raise can't be called inline
And or would return the first?
presumably because it's not an expression
i know, i'm just remarking at it as a design choice
Wasn't it you who was on a soapbox about how any and all should operate that way?
Or was that Godly
what way?
any should return the first truthy object from an iterator
you mean making raise a statement?
100% not me
because I don't think that
Must have been godly
yes
I agree: any should return the truthy value it finds.
Why not reduce with or?
why?
hm isn't it a statement in most languages
because it would be more useful.
as an operation that has a side effect
and also very poorly named
I feel like the current use is more idiomatic
that would probably find some use for me
i'm ok with the name being a little odd
a little?
i've definitely had to bool(None) at least once somewhere
all([6, 1, 0]) is 0 <- ???
nice
yes, but it would be nice if it weren't
for example, c# allows for throw expressions
I must admit to using statements in ? in JS
er, wait - if you reduce a list of objects by sticking and between each: py accumulator = True for elem in lst: accumulator = accumulator and elem Then at the end, accumulator will be set to the first falsey value in the list, or the last value in the list if there are no falsey values.
the reason why it would be nice is to dynamically change what is being "thrown" at runtime
that's fair
Why can't you handle that in python?
what's throw mean here
!e
e = ValueError
raise e
@gleaming rover :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | ValueError
I assumed the exception type to be caught
you can catch one type of error and throw another? or what is it you want?
where the throw is triggered
You can construct any exception you want, before throwing it
"the end"? You can do it anywhere you can run a statement
!e ```py
import random
exc_type = random.choice([ValueError, TypeError])
exc = exc_type("Whoops")
raise exc
@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 | TypeError: Whoops
def random_number_generator():
return 4
!e If you really want to use raise as an expression, you can get reasonably close with ```py
def raise_(e):
raise e
print("foo".isdigit() or raise_(ValueError("Not a number")))
@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 | File "<string>", line 2, in raise_
004 | ValueError: Not a number
yes, this is often what ends up happening
can you raise in a lambda
no, raise is a statement
no IIRC
no
syntax error
rip
can't stop me:
In [10]: (lambda: 1/ 0)()
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-10-66611d42095c> in <module>
----> 1 (lambda: 1/ 0)()
<ipython-input-10-66611d42095c> in <lambda>()
----> 1 (lambda: 1/ 0)()
ZeroDivisionError: division by zero
!e I mean, you can do ```py
(lambda: exec("raise ValueError('oops')"))()
@raven ridge :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 1, in <lambda>
004 | File "<string>", line 1, in <module>
005 | ValueError: oops
here's something you'll hate. When I was working on nurses, I added a decorator inside my Widget class that would turn attributes into properties automatically:
@bind_to("top")
def _set_pos_hint_y(self):
self.pos_hint = None, self.pos_hint[1]
now doing my_widget.top = 5 would call the decorated method
the metaclass for this is absolutely disgusting
I'd like to see it
looks through all the base classes for the attribute and replaces it with a property
why not use rich?
Doesn't seem that ugly
it looks extremely ugly. like, where does _attr_to_callbacks even exist
oh nvm, I see it
you didn't leave spaces between your function
it's "part" of the function, which is why it's stuck to it like that
it's mutable, best not to put it in args, i could attach it as an attribute of the decorator, that seems weird to,
and mutable args stay with the function 🤡
i didn't use rich because, updating rich in "real-time" causes lots of screen flickering
ah, gotcha
this library is async, and i wrote it for my own edification
Personally I would have made binds_to a descriptor decorator that added the call backs to the owner class in __set_name__
it's simply a project to hammer on when i'm bored
But that might have been too late to work with __new__ on type¿
it's a weird meta-hole, you could just be perfectly explicit about everything and require people declare properties as normal in the class definition
but i like to be lazy when writing new widgets
Why not descriptors as decorators??
That way _attrs_to_callbacks isn't in the module scope
i don't know what you mean
You can make descriptors that act like property by implementing __call__ on the descriptor class
And then in __set_name__ you have access to the owner class
You're not using __call__ though
I'm saying you could make your metaclass more sane by making bind_to a descriptor decorator
By making a descriptor class that implements __call__
you mean it does that same thing, but callbacks would temporarily be stored as an attribute?
Basically in __set_name__ you'd be adding what you add to _attr_to_callbacks in the module scope to _attr_to_callbacks in the class scope
Then the call backs are defined in the class at least
maybe, all the callbacks end up in the Observable dicts in the end
I just think that's saner than effectively having to manage the state of a module level variable within __new__ of your metaclass
i think i see what you're saying -- bind_to should be a new instance of the thing everytime?
Actually I'm pretty sure if you implemented __call__ on Observable then you could get rid of your metaclass all together
i don't see how
Bc
Implementing __call__ on a descriptor will go through the following methods I'm pretty sure
Call -> init-> set name
The call allows you to use the descriptor as a decorator
And what you are passing to call will be the thing you are decorating
this would be a normal way:
class MyWidget:
height = Observable()
def __init__(self, ...):
height.bind(self.resize)
but meta allows this:
class MyWidget:
@bind_to("height")
def resize(self, ...):
...
i know i could add a __call__ to observable, but then my decorator would look like:
@Widget.height
def resize(self, ...)
which means i already defined the height as a property the normal way
Is there a magic command for copying code, in ipython
i just select it with mouse and ctrl+c
class Descriptor:
def __init__(self, *args, **kwargs):
print("__init__")
print(args)
print(kwargs)
def __set_name__(self, owner, name):
print("__set_name__")
print(owner)
print(name)
def __call__(self, fnc):
print("__call__")
print(fnc)
self.func = fnc
return self
def __get__(self, instance, owner):
print("__get__")
print(instance)
print(owner)
return self.func(self)
class Foo:
@Descriptor(1,2,b=5,c=6)
def bar(self):
return "bar"
f = Foo()
f.bar
I'm saying, the machinery is there for you to get rid of your metaclass I am pretty sure
__call__ acts as your decorator replacing your bind_to and then in __set_name__ you can register the stored function passed in __call__ to the _attr_to_callbacks defined on your class
i wrote bind_to the way that i did because it's the simplest thing to type out
All you seem to be doing is making anything decorated with bind_to to an Observable descriptor
I am saying you utilize __call__ on Observable and you can do that, without the need for a metaclass.
but how does that help my metaclass? The metaclass sees that a possibly normal attribute needs to be bound to a function -- it looks for that attribute in the class dict and then the dict of the base classes until it finds it, and if it's not able to be bound to a function, it redefines that attribute into a property that can be bound to a function -- or several functions
this is extreme surgery so that i can be lazy when defining new widgets
owner in __set_name__ is the class. You can shift that metaclass logic into there
is what class?
In the class of the method you are decorating
__set_name__ is only called automatically when descriptor is instantiated and assigned in the class body
Like you're basically looking for things stored in _attr_to_callbacks and checking to see if they aren't already Observable and then making them so if not.
ok maybe I skimmed bit too fast and missed this for base in bases:
I still think that mro logic would be handled naturally in the descriptor decorator
is there anything wrong with doing this to disable then later enable the calling of an object's function?
`class TestC:
def init(self):
# disable calling func1 initially
self.func1 = None
return
def func1(self):
pass
# enable func1 for calling
def enable_func1(self):
self.func1 = func1
return
tc = TestC()
tc.enable_func1()
tc.func1()`
there's some weird stuff going on, the reason for this:
def dispatch(self, instance):
# Build list of dispatches from _mro_ if it doesn't exist
name = type(instance).__name__
if name not in self.callbacks:
d = { }
for base in reversed(type(instance).__mro__):
d.update(self.methods.get(base.__name__, { }))
self.callbacks[name] = list(d)
for callback in self.callbacks[name]:
getattr(instance, callback)()
is so the same method isn't called multiple times if it's bound in a parent and a child
This metaclass will search for any attributes what were added to
_attr_to_callbackswith thebind_to
decorator in a Widget class definition. If those attributes aren'tObservablethey will be redefined as
Observable so that the decorated methods can be bound to the attributes.
Like reading that, I clearly don't see how that metaclass logic can't be completely self contained within Observable by utilizing __call__ and __set_name__, this would make bind_to completely obsolete
i mean show me what you mean, maybe it can be, i have no idea what you mean though
I thought I did with this
!e
class Descriptor:
def __init__(self, *args, **kwargs):
print("__init__")
print(args)
print(kwargs)
def __set_name__(self, owner, name):
print("__set_name__")
print(owner)
print(name)
def __call__(self, fnc):
print("__call__")
print(fnc)
self.func = fnc
return self
def __get__(self, instance, owner):
print("__get__")
print(instance)
print(owner)
return self.func(self)
class Foo:
@Descriptor(1,2,b=5,c=6)
def bar(self):
return "bar"
f = Foo()
f.bar
You are not allowed to use that command here. Please use the #bot-commands channel instead.
I'm not allowed to of course
i don't know how this is similar to what i'm doing
execute it really quick and look at the prints?
!e
class Descriptor:
def __init__(self, *args, **kwargs):
print("__init__")
print(args)
print(kwargs)
def __set_name__(self, owner, name):
print("__set_name__")
print(owner)
print(name)
def __call__(self, fnc):
print("__call__")
print(fnc)
self.func = fnc
return self
def __get__(self, instance, owner):
print("__get__")
print(instance)
print(owner)
return self.func(self)
class Foo:
@Descriptor(1,2,b=5,c=6)
def bar(self):
return "bar"
f = Foo()
f.bar
@deft pagoda :white_check_mark: Your eval job has completed with return code 0.
001 | __init__
002 | (1, 2)
003 | {'b': 5, 'c': 6}
004 | __call__
005 | <function Foo.bar at 0x7f2f0bb6e1f0>
006 | __set_name__
007 | <class '__main__.Foo'>
008 | bar
009 | __get__
010 | <__main__.Foo object at 0x7f2f0bb72dc0>
011 | <class '__main__.Foo'>
See in __call__ you get the method you are decorating, and can store it. Then in __set_name__ you have access to the class. All the same information you have in metaclass __new__
ok?
So within __set_name__ you can do all that __new__ logic.
i'm not seeing it
Can you elaborate on what part you aren't seeing?
not really
Like I would showyou but I'd have to fork your repo
I'll get back to you, because its late and I am east coast. I'll fork it tomorrow and show you
who makes python and how can i make me some python
how would one type hint a nested dictionary? eg { 'a' : { 'b' : 1 }, 'c' : {'d' : 2} .
def f(_dict : dict):
pass
dict[str, dict[str, int]]
``` (or with typing.Dict pre 3.9)
ah, ok, thanks - and if they were int or float i would use dict[ str, dict[str, (int, float)]] ?
oh, maybe i still need union, oh ok, hrm
If you have a fixed set of keys, use TypedDict
why does str.join require string iterables, can't it just run str() on them? it would make things a lot easier, especially for beginners that aren't comfortable with writing generators like str(x) for x in iterable, the function will always only use strings, so it might as well run str automatically, I'm just curious why it doesn't do that?
python generally doesn't coerce types (except bool and in some instances int), so it wouldn't be all that idiomatic and you could get some odd bugs arising from it.
#Python user poll: Would you like str.join() to work like print() and automatically coerce its arguments to strings?
Given:
data = [10, 20, 30, 40, 50]
Which do you prefer?
116
it's a bit of a controversial issue, it seems
people really hate weak typing seems to be the consensus
especially since they are familiar with the pitfalls of JS in this regard
but it does look nicer for quite a few cases
well,
yeah, I was referring to the complaints
ah
I do mostly agree that it would help more than it would harm, and you seldom see ''.join used with lists of full objects
You'd have the issue of getting <genexpr at 0x13ab3c> <genexpr at 0x57e5a7c> <genexpr at 718e5272> in your string 
Yes, I do that very often
print
that said...
I was originally "no that's a really bad idea" then I thought of what print does and now I'm like "...I still think it's a kinda bad idea"
What's wrong with print?
Yes, tired of doing things like
"".join(map(str, iterable))
I think str.join should coerce if there's a __str__ implemented on the object
print can also write to a file 👀
!e
Actually, you can use automatic coercion like this (#esoteric-python
):
from io import StringIO
iterable = [1, 2, "foo", {"b", "a", "r"}]
s = StringIO()
print(*iterable, sep=" & ", end="", file=s)
s.seek(0)
print(s.read())
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
1 & 2 & foo & {'a', 'b', 'r'}
no need for str.join!
Seeking and calling read is unnecessarily esoteric, you can just call getvalue instead.
"unnecessarily esoteric"
Are file buffer pipes a thing in the stdlib?
You can make them. open accepts a file descriptor, and os.pipe produces a pair of file descriptors.
ah
right...
!e ```py
import os
r, w = os.pipe()
print("hello", file=open(w, "w"))
x = open(r).read()
print(x)
@raven ridge :white_check_mark: Your eval job has completed with return code 0.
hello
didn't know that
Hah, nice
So if you pipe sys.stdout to open(1) you have effectively string coercion?
open(1)? Nah, you can't do that, AFAIK. fd 1 is opened only for writing, not for reading.
Or I'm not understanding what you mean. Because, when the interpreter starts up fresh, sys.stdout already writes to fd 1
for some reason i thought that if i passed the wrong type to a typed function it would raise a type error
only just bothered with typing, is there anyway to have it validate type like that? or not
There's no way to have the interpreter validate it, no.
For a good reason: if you type hint a function with ```py
def foo(x: list[int]) -> None:
You could use a tool like mypy I guess
https://pypi.org/project/pydantic/ exists and can do some level of opt in runtime checking.
yeah that wont error in a notebook or something tho will it?
like if i have some
def f(x: int) and pass f('this') it'd be nice if there was automatic checking, along the lines of
if not isinstance(x, int):
raise TypeError(f'expected x to be type int, got {type(x)}')
is the reason why that doesn't, in general, work.
I guess if you have an internal field saying the type of the value inside of the list you'd avoid this
Assuming that the field is kept up to date when the list is updated
For another example, consider a function that accepts an iterator. It's supposed to get an iterator of ints, but there's no way to check that that's what it got without consuming elements from the iterator.
or an infinite iterator which may be impossible to verify altogether
its not too hard to make something like a decorator to try this but if you do, its probably best you dont try to check the contents of containers, only the type of the object itself
I guess in this instance you maaayybe assume the type of the iterator and raise if it yields something invalid
That doesn’t really work though
It'd be nice if it did everything but infinite iterators I guess
I mean if you reaaaaally restrict your iterator domain to arrays, you can then check the type of the array but that probably defeats the point in most cases
the issue is
class EvilList(list):
def __getitem__(self, i):
if random.random() < 0.01:
return 'unlucky'
return super()[i]


