#internals-and-peps

1 messages · Page 83 of 1

flat gazelle
#

at Then people are dumb

safe hedge
#

Surely you should just trust the docs RE: behaviour. Simply going by observation feels a bit like thinking a coin is bias because you did 5 flips and got 5 heads?

#

Relying on something that isn't documented is kind of silly no?

desert peak
#

@flat gazelle wrong words. people shouldn't have to be clever to write python

#

you want smart people writing code

flat gazelle
#

you do, but even dumb people should manage

safe hedge
#

If the docs say "dict order is not guaranteed" that is fine. Even if a particular implementation happens to cause it to be guaranteed

flat gazelle
#

I don't check the docs for every little oddity I find, there would definitely be at least a few people who would decide to use it out of laziness

#
list(dict.fromkeys(l))```vs
```py
ls = set()
r = []
for elem in l:
    if elem not in ls:
        ls.add(elem)
        r.append(elem)
#

it is useful enough that I think even the docs would make go: eeeh, I will fix it later

safe hedge
#

There are plenty of things where quirks can trip you up though no?

>>> n = 1 
>>> n2 = 1 
>>> n is n2
True
>>> n = 14
>>> n2 = 14
>>> n is n2
True
>>> n = 10000
>>> n2 = 10000
>>> n is n2
False
#

Like this behaviour can get people

radiant garden
#

The assumption here is that the documentation gets read. That's not always a given. Especially because the docs are less visible in search results than endless tutorial sites.

#

(re: rtfm)

flat gazelle
#

yes, that is an annoying quirk. But it is easy to fix, since you can just replace is with==. There are other things which would be nicer to have to deal with, but its not horrible.

empty kite
#

@unkempt rock Ordered dicts are nice for building GUIs. Saves you from having to use collections.OrderedDict everywhere

thorny nimbus
#

Why is wierd behaviour at last lines of code above

safe hedge
#

It's not weird

#

It's the fact that is is being abused

flat gazelle
#

integers from -3 to 255 are cached and always use the same instance

#

all other integers are allocated anew

radiant garden
#

is with comparison a literal raises a warning in most use cases

#

afaik

safe hedge
#

Yeah it does

feral cedar
#

!e 1 is 1

fallen slateBOT
#

@feral cedar :white_check_mark: Your eval job has completed with return code 0.

<string>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
safe hedge
#
>>> 1 is 1
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
#

Ha beat me to it

flat gazelle
#
In [14]: x = "HelloWorld"
In [15]: y = "Hello" + "World"
In [16]: x is y
Out[16]: True
In [17]: x = "Hello World"
In [18]: y = "Hello " + "World"
In [19]: x is y
Out[19]: False
#

though I don't think I ever saw this in real code

desert peak
#

can't ordereddict be enumerated by int?

flat gazelle
#

generally people figure out is vs == by strings

safe hedge
#
>>> 0 is False
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False
>>> 0 == False
True
#

This is fun

thorny nimbus
#

We should try to reduce the use of is operator

flat gazelle
#

there are very few uses for is

#

mostly for comparisons with None

desert peak
#

there is one use for is: identity.

#

which applies to singletons like None, True, and False every time

flat gazelle
#

also NotImplemented

desert peak
#

isn't NotImplemented an Error?

flat gazelle
#

NotImplemented is a singleton, NotImplementedError is an error

desert peak
safe hedge
#

Is ... a singleton?

flat gazelle
#

yes

desert peak
#

I've never seen NotImplemented used as an object

safe hedge
#

!d NotImplemented

fallen slateBOT
#
NotImplemented```
Special value which should be returned by the binary special methods (e.g. [`__eq__()`](../reference/datamodel.html#object.__eq__ "object.__eq__"), [`__lt__()`](../reference/datamodel.html#object.__lt__ "object.__lt__"), [`__add__()`](../reference/datamodel.html#object.__add__ "object.__add__"), [`__rsub__()`](../reference/datamodel.html#object.__rsub__ "object.__rsub__"), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. [`__imul__()`](../reference/datamodel.html#object.__imul__ "object.__imul__"), [`__iand__()`](../reference/datamodel.html#object.__iand__ "object.__iand__"), etc.) for the same purpose. It should not be evaluated in a boolean context.

Note... [read more](https://docs.python.org/3/library/constants.html#NotImplemented)
wide shuttle
#

It's a special value that you return if you don't implement a dunder in a certain instance

#

It allows Python to look for an implementation in the class of the object on the other side of the operator

flat gazelle
#

oh, oops

desert peak
#

ah, interesting

wide shuttle
#
class Foo:
    def __init__(self, value):
        self.value = value

    def __lt__(self, other):
        if not isinstance(other, Foo):
            return NotImplemented

        return self.value < other.value
desert peak
#

I've never had a need for it. that's nice

wide shuttle
#

In this case, if you use anything but an instance of (a subclass of) Foo at the other side of the <, you return NotImplemented

flat gazelle
#
In [27]: 4 .__mul__('aaa')
Out[27]: NotImplemented```
wide shuttle
#

This allows Python to then look for an implementation in the other class

safe hedge
#

Weirdly it has a bit of a quirk amongst the python singletons:

>>> NotImplemented = 'a string'
>>> True = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to True
>>> False = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to False
>>> None = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to None
>>> __debug__ = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to __debug__
>>> ... = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to Ellipsis
wide shuttle
#

Yeah, in this case, the int does not define a multiplication with a str, but str does implement multiplication with integers

flat gazelle
#

yeah, its not really important enough for a syntax level singleton, so its just a builtin.

wide shuttle
#

So, if you do 4 * "aaa", Python will first look for an implimentation in int for 4, does not find one there, and then goes on to "aaa" to see if it makes sense there

#

Which it does, so you get "aaaaaaaaaaaa"

safe hedge
#

And now I am veryyyy confused:

>>> ... is Ellipsis
True
>>> Ellipsis = 'a string'
>>> ... = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to Ellipsis
desert peak
#

lol

#

that is quite confusing

peak spoke
#

... is probably a special case in the identifier rules

wide shuttle
#

Ellipsis is one of the built-in constants, and the same as the literal ...

safe hedge
#

Yeah, I guess I just assumed they would behave the same

#

Like behave identically

wide shuttle
#

One is a literal, but the other is just a name that's not protected like False and True are

peak spoke
#

ah, it's not even an identifier apparently, so it gets refused as any other literal with a bit different text

safe hedge
#

Just makes me laugh:

>>> ...
Ellipsis
>>> Ellipsis
'a string'
>>> 
wide shuttle
#

NotImplemented also isn't protected

#
>>> NotImplemented = "foo"
>>>
safe hedge
#

Yeah I noted that up there somehwere^

desert peak
#

does the ! symbol have a use in Python? I can't remember

peak spoke
wide shuttle
#

Ah, missed that

peak spoke
#

Don't think it's used anywhere other than != and the format language

wide shuttle
#

There's !=

#

And, yeah, the conversion specifiers in string formatting

#

Other uses don't come to mind

peak spoke
#

$,? and ` aren't used anywhere as syntax

#

(at least not direct python syntax)

thorny nimbus
#

May be in future Python versions they may take advantage of these symbols I guess

peak spoke
#

? Has a few proposed uses, don't like ` too much for any syntax

safe hedge
#

https://docs.python.org/3/library/constants.html mentions the 4 "proper" constants
@peak spoke What is up with ...? I know it's a literal but it does seem to be different to other literals:

>>> 1 = 10
  File "<stdin>", line 1
SyntaxError: cannot assign to literal
>>> ... = '1'
  File "<stdin>", line 1
SyntaxError: cannot assign to Ellipsis
grave jolt
#

well, it's just... ellipsis

desert peak
#

It's a Singleton in the family of None and co.

safe hedge
#

It gets a specific SyntaxError message like True/False etc, but the value it refers to Ellipsis can actually be assigned to

#

As I showed above

#

So it's kind of odd

peak spoke
#

Would probably have to look into the source for why it's handled like that. But id guess it's because if the dot syntax which is already used for attr access

undone hare
safe hedge
#

It's just funny to me that Ellipsis appears to be a builtin constant for the literal ... so then when you try assigning to ... it tells you it can't assign to the literal Ellipsis then when you assign to Ellipsis it works haha

#

I guess cannot assign to ... might have looked a bit strange as a message

undone hare
#

!e

import dis
dis.dis('... = 42')```
fallen slateBOT
#

@undone hare :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "/usr/local/lib/python3.8/dis.py", line 38, in _try_compile
003 |     c = compile(source, name, 'eval')
004 |   File "<dis>", line 1
005 |     ... = 42
006 |         ^
007 | SyntaxError: invalid syntax
008 | 
009 | During handling of the above exception, another exception occurred:
010 | 
011 | Traceback (most recent call last):
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/jaxupofaku.txt

undone hare
#

Oh

#

Yeah

safe hedge
#

I wonder if you can break numpy by assigning to Ellipsis. It seems to use Ellipsis in a couple of places

wide shuttle
#

You will just shadow it with a name in your module-level globals

#

It won't actually "break" the name internally

#

Just like assigning to the name list

#

Depending where and how numpy uses it, you may or may not see issues

safe hedge
#

It uses it in like a two modules

wide shuttle
#

I wonder if you could break it by patching the builtins

#

That should work, I think

safe hedge
#

lib.arraypad, lib.shape_base, and core.shape_base I think

#

I don't know enough about numpy to know where the code it's used in has effect

peak spoke
#

Yeah __builtins__ are shared

wide shuttle
#

Say that you have a two.py with this in it:

def foo():
    return Ellipsis

and then have a one.py with this:

from two import foo
import builtins


Ellipsis = "One"
print(foo())  # prints Ellipsis

builtins.Ellipsis = "One"
print(foo())  # prints One
undone hare
#

Could also reassign the c pointer

safe hedge
#

Ah right yeah

#

What is happening here:

>>> __builtins__.True
  File "<stdin>", line 1
    __builtins__.True
                 ^
SyntaxError: invalid syntax
>>> __builtins__.Ellipsis
Ellipsis
desert peak
#

does python have a builtin random string generator for like passwords?

spice pecan
#

!d secrets

fallen slateBOT
#

New in version 3.6.

Source code: Lib/secrets.py

The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

In particular, secrets should be used in preference to the default pseudo-random number generator in the random module, which is designed for modelling and simulation, not security or cryptography.

undone hare
#

@safe hedge that’s the fault of the parser

desert peak
#

Ooo sick, thanks @spice pecan

safe hedge
#

@undone hare ah

#

What is failing with the parser?

undone hare
#

I’ll let our dear Batuhan anwser haha

true ridge
#

Weirdly it has a bit of a quirk amongst the python singletons:

>>> NotImplemented = 'a string'
>>> True = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to True
>>> False = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to False
>>> None = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to None
>>> __debug__ = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to __debug__
>>> ... = 'a string'
  File "<stdin>", line 1
SyntaxError: cannot assign to Ellipsis

@safe hedge for True/False/None, they are embedded in the grammar. NotImplemented and Ellipsis are kept as normal names. The thing with __debug__ is, it is actually preventing changing the code flow. On the compile time __debug__ is optimized depending on the flags passed into the compiler, so if __debug__: print(1) would just appear if you disable __debug__ and vice verse. For preventing users to mess with this, assigning to __debug__ is disabled (since runtime assignments won't have any affect on compile time optimizations)

#

The reason that changing the value of builtins.Ellipsis won't change the value of ... is, it is also embedded in the grammar to statically point to the real Ellipsis object rather than a lookup to the builtins.Ellipsis on each ocurrence

#

The error messages actually from the same place, but we have special conditions against True False etc.

safe hedge
#

I guess then the question is why ... and not Ellipsis too?

#

And then finally why does my interactive interpreter throw a syntax error on __builtins__.True and __builtins__.False?

true ridge
#

As I said, True and False are parsed as constants not normal names

#

so you can't actually chain them as normal attributes

#

just like you can't actually access an attribute that is not a valid identifier like "$"

#

you could use setattr/getattr for these though

peak spoke
#

It is also mentioned in the page I linked previously that they're forbidden also as attrs

#

Direct assignment to the dicts only cares about them being strings right?

true ridge
#

I guess then the question is why ... and not Ellipsis too?
@safe hedge for this, I dont know for sure. If you have time, probably you could search for discussions in the time of introducement of Ellipsis to figure out

#

Direct assignment to the dicts only cares about them being strings right?
@peak spoke what do you mean by direct assignment?

#

a[b] = c?

safe hedge
#

It is also mentioned in the page I linked previously that they're forbidden also as attrs
@peak spoke Literally that was where I started this rabbit-hole journey from, and how I realised NotImplemented wasn't protected. I just blanked on the second half of that note hahah

peak spoke
#

Yeah going through the globals builtin or the setattr you mentioned

safe hedge
#

Hoisted by my own petard RE: RTFM from earlier haha

peak spoke
#

The first time I noticed the attes was when I found out you can access pretty much any string in strings through format

true ridge
#

AFAIK (seen in the past, might be not the case for now) when pytest is rewriting the assertions (to get a prettier output) they use $ prefix to normal names on their constructed AST

#

So that it wouldn't suppress anything on the scope

desert peak
#

why does ellipsis exist?

peak spoke
#

I couldn't really find the intial reason last time I checked as it already existed for python 1

true ridge
#

I remember seeing discussions that it was existed to support a.b[...] syntax only

#

but need to check

wide shuttle
#

I think that's one of the things mentioned in Fluent Python, that it was to have things like a[1:3, ..., 4] slice notations

#

I think it was even only allowed in slice notation before Python 3

#
sebastiaan@sebastiaan-N53SV:~$ python2.7
Python 2.7.18 (default, Aug  4 2020, 11:16:42) 
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> ...
  File "<stdin>", line 1
    ...
    ^
SyntaxError: invalid syntax
>>> class Foo:
...     def __getitem__(self, i):
...             return i
... 
>>> f = Foo()
>>> f[...]
Ellipsis
true ridge
#

One thing that I remember from python 2 times was a[. . .]

#

infinite whitespace allowed between each dot on py2

safe hedge
#

erm...

desert peak
#

an empty slice shallow copies a list, right? [:]

spice pecan
#

yeah

desert peak
#

is there similar behavior for dicts or other builtin collections?

spice pecan
#

Likely true for the ones that allow slices, since empty slices get filled with start=0, stop=length, step=1

#

For dicts you can use their .copy method, for example

desert peak
#

is slice behavior just syntax sugar for a method call?

#

if so, which?

spice pecan
#

In python3, slicing is syntactic sugar for creating a slice object and passing it to the same dunders that cover regular indexing, so __getitem__, __setitem__ and __delitem__ (I think?) (Yeah, __delitem__ is a thing)

#

!d slice

fallen slateBOT
#
class slice(stop)``````py
class slice(start, stop[, step])```
Return a [slice](../glossary.html#term-slice) object representing the set of indices specified by `range(start, stop, step)`. The *start* and *step* arguments default to `None`. Slice objects have read-only data attributes `start`, `stop` and `step` which merely return the argument values (or their default). They have no other explicit functionality; however they are used by Numerical Python and other third party extensions. Slice objects are also generated when extended indexing syntax is used. For example: `a[start:stop:step]` or `a[start:stop, i]`. See [`itertools.islice()`](itertools.html#itertools.islice "itertools.islice") for an alternate version that returns an iterator.
wide shuttle
#

The elipsis was mainly added for numpy (and other third-party frameworks that wanted to take advanced of it)

#

Say, you have a[1, :, :, :, 2] in numpy

#

That's equivalent to a[1, ..., 2] (in numpy!)

undone hare
#

I like using the elipsis as a placeholder for a function body that I’ll write later

wide shuttle
#

saving one char of pass

spice pecan
#

The ellipsis didn't have a use in the stdlib until relatively recently, when it got a use in typing IIRC

wide shuttle
#

I typically just add a docstring for that purpose, so that I have a description of the function I still need to write

undone hare
#

I see pass more as a way to declare an empty body, rather than just a placeholder

true ridge
#

Yeah, the only advantage of Ellipsis over pass is it is an expression. So if you are trying to encode some sort of math formula, like x = A * (2 + b) - 5 + ... * 4 etc it might be handy to not to forget put there something

grave jolt
#

I don't really see the need for pass tbh

#

since it can be replaced with ...

#

...or a docstring!

peak spoke
#

I feel like it better communicates the intent in some cases

undone hare
#

There are some legitimate cases where you’d want an empty body, like if you need to have an empty with statement, I feel like it communicates best that you don’t have to do anything in there, you just pass it

cloud crypt
#

^

unkempt rock
#

what would the purpose of an empty with statement be?

grave jolt
#

for the side effects

#

!e

class X:
    def __enter__(self):
        print("foo")
        return self

    def __exit__(self, *args):
        print("bar")
        return False

with X():
    ...
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 | foo
002 | bar
flat gazelle
#

or for exception handling

grave jolt
#

well, ... can't throw any exceptions, right

#

but the unpacking in with can fail

#

like

#

!e

class X:
    def __enter__(self):
        print("foo")
        return []

    def __exit__(self, *args):
        print("bar")
        print(args)
        return True

with X() as [a, b, c]:
    ...
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 | foo
002 | bar
003 | (<class 'ValueError'>, ValueError('not enough values to unpack (expected 3, got 0)'), <traceback object at 0x7f5ac7d41c80>)
unkempt rock
#

for the side effects
@grave jolt side effects are gross!

#

but ok i see your point

grave jolt
#

well... if a program doesn't produce any side effects, it's pretty useless 🙂

unkempt rock
#

?

#

functional programming is a thing

grave jolt
#

A functional program still produces side effects.

unkempt rock
#

meh

#

they wouldnt use a passed with statement to print out 'foo' hehe

flat gazelle
#

the result of a haskell program is a very complex side effect

grave jolt
#

well, yes, Python isn't a functional programming language

#

and things like that are pretty gross

unkempt rock
#

ye

grave jolt
#

I don't think I ever needed an empty with

flat gazelle
#

I used the redirect stdout once or twice

unkempt rock
#

imagine coding an entire program by using enter exit context managers

#

O_O

#

horrifying

grave jolt
unkempt rock
#

disgusting

#

i love it

stray hollow
#

My god

#

It's almost as bad as whitespace

unkempt rock
#

ya stupid whitespace

#

w-wait python uses whitespace

stray hollow
#

This is what I'm talking about

unkempt rock
#

o-oh

#

i want to cry

#

its horrible

sacred yew
#

whitespace isn't even the worst esolang 😛

desert peak
#

!ot

fallen slateBOT
brave raven
#

class X:
def enter(self):
print("foo")
return []

def __exit__(self, *args):
    print("bar")
    print(args)
    return True

with X() as [a, b, c]:
...

unkempt rock
#

Hi. I have experience programmming in python and solving engineering problems using python.
I would like to improve my software development skills in python -> designing maintainable software by using OOP concepts etc.
Can anyone suggest resources and opensource projects which can help?

undone hare
trail marsh
#

Can anybody explain what are two problems caused by the deepcopy through examples as mentioned in this documentation

#

``Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.

Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.``

#
>>> from copy import deepcopy as dc
>>> l = [1, 2, [3, 4, [5, 0]]]
>>> d = dc(l)
#

The 2 nd point is , while we create d from l unnecessary elements such as l[0],l[1] is enough to be copied no need to get deepcopy as they are imutables hence consuming more data( The data is enough to be just copied rather than deepcopied)

unkempt rock
#

import random

def random_graph(n):
R = [[0] * n] * n
for i in range(0, (len(R)*len(R))):
a = random.randint(i, n - 1)
b = random.randint(i, n - 1)
if a==b:
R[a][b] = 0
R[b][a] = 0
elif a!= b:
R[a][b] = 1
R[b][a] = 1
return R

grave jolt
#

@unkempt rock This is not a help channel, this is a discussion channel. See #❓|how-to-get-help an open a help channel.

unkempt rock
#

thanks

desert peak
#

what are the cases when __call__ is invoked?

#

I'm seeing some example cases where method overrides to __call__ are doing super().__call__ instead of super()() just curious why that would be the case

flat gazelle
#

when you call an instance of the class and when you specify the class as a metaclass. As for the super thing, that is just convention to make it visually similar to other super method calls

desert peak
#

so which is more "correct" super()() or super().__call__()?

#

!d super

fallen slateBOT
#
super([type[, object-or-type]])```
Return a proxy object that delegates method calls to a parent or sibling class of *type*. This is useful for accessing inherited methods that have been overridden in a class.

The *object-or-type* determines the [method resolution order](../glossary.html#term-method-resolution-order) to be searched. The search starts from the class right after the *type*.

For example, if [`__mro__`](stdtypes.html#class.__mro__ "class.__mro__") of *object-or-type* is `D -> B -> C -> A -> object` and the value of *type* is `B`, then [`super()`](#super "super") searches `C -> A -> object`.

The [`__mro__`](stdtypes.html#class.__mro__ "class.__mro__") attribute of the *object-or-type* lists the method resolution search order used by both [`getattr()`](#getattr "getattr") and [`super()`](#super "super"). The attribute is dynamic and can change whenever the inheritance hierarchy is updated.... [read more](https://docs.python.org/3/library/functions.html#super)
flat gazelle
#

I would say either is fine

desert peak
#

okay, so super() would never return a type

wide shuttle
#

I've never seen super()() in real life and I would be a bit confused

#

Does it work?

#

Since super returns a proxy object

#

Probably

desert peak
#

hmm, good point. Let me test my example

flat gazelle
#

it does not

wide shuttle
#

I don't think it works. You'll probably get something along the lines of "super object not callable"

#

but, I can't test it right now

flat gazelle
#

huh, that does make sense, I guess it would be a bit silly to delegate dunders

desert peak
#

I guess this is why __init__ gets explicitly called, too

flat gazelle
#

well, how would you do that with __init__

#
In [8]: class U:
   ...:     def __call__(self):
   ...:         print('aha')
   ...:

In [9]: class V(U):
   ...:     def u(self):
   ...:         super()()
   ...:

In [10]: V().u()
------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-c8ce57f13006> in <module>
----> 1 V().u()

<ipython-input-9-a13c917bc4ad> in u(self)
      1 class V(U):
      2     def u(self):
----> 3         super()()
      4

TypeError: 'super' object is not callable
desert peak
#

oh weird, so super is just a proxy

raven ridge
#

Reposting a question from #c-extensions here:

How do I assert that an object has a __call__() that takes a certain number of arguments?
@misty oxide

So far as I know, there's not any great way to do this that works for all types of callables (bound methods, things taking *args, etc), and normally you just have to call the thing and see if it works. Anybody know of better ways?

spice pecan
#

You could technically inspect the method's __code__ attribute and check the amount of args, but *args definitely do throw a curveball in, yeah

#

I'd just go with try-except

misty oxide
#

oof

#

Also, this has to be done from C code

spice pecan
#

I think it's easier to check in C code than in Python code tbh

radiant fulcrum
#

i mean doing it in python could just be done with inspect no?

spice pecan
#

inspect.signature could work IG

desert peak
#

just a joke I wanted to share with you folks and a curiosity: is true immutability possible? or only with like, C extensions?

peak spoke
#

You could use the same ways to go around other ways of implementing it that you can use for current immutable builtins

raven ridge
#

Even C extensions don't give true immutability - users can still (ab)use ctypes to modify immutable data.

flat gazelle
#

C also cannot really enforce immutability. It just calls it UB when you break it, but it can be broken

raven ridge
#

yeah. A tuple is immutable, but a tuple is implemented as an array of PyObject* pointers in writable memory. If someone overwrites one of those pointers, the tuple contains different items. And ctypes gives you the tools to do so, in pure Python code. You can even change things like the values of the cached integer constants.

pliant tusk
#

Yea nothing in python can be truly immutable

desert peak
#

huh, that's fascinating.

#

I've never had a need to reach into ctypes

unkempt rock
#

Does anyone mind giving an example of how you can use ctypes to modify immutable objects? Seems interesting

pliant tusk
#

depends on the immutable object

raven ridge
#

Does anyone mind giving an example of how you can use ctypes to modify immutable objects? Seems interesting
@unkempt rock well into undefined behavior, but here:

#

!e ```py
import ctypes
obj = b"foo"
print(obj)
ctypes.memmove(id(obj) + 32, b"bar", 3)
print(obj)

fallen slateBOT
#

@raven ridge :white_check_mark: Your eval job has completed with return code 0.

001 | b'foo'
002 | b'bar'
raven ridge
#

byte strings are immutable, but ctypes lets me mutate it anyway.

#

that relies on several different CPython implementation details, so, ya know, don't actually do that, heh

unkempt rock
#

Interesting, thanks

desert peak
#

what stops objects from having arbitrary attributes?

#

I've noticed if I create an object(), I can't assign attributes, but I can with my own types class Test: pass

#
In [1]: a = object()

In [2]: a.a = 5
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-2-17f85e12aec5> in <module>
----> 1 a.a = 5

AttributeError: 'object' object has no attribute 'a'

In [3]: class Test: pass

In [4]: t = Test(); t.a = 5

In [5]: t.a
Out[5]: 5
radiant fulcrum
#

slots?

torpid pollen
#

"A Python-List is an object that contains multiple data items, you are expected to use the proper list functions to do the following activity.

Design a python application that prompts the user three times for three number values (integer or float) one by one. The application prints these three values and finally uses list functions to find and print the maximum and the minimum of these number values.

Please run the program three times and change the order of the integer values you enter such that the maximum number you enter is at different position at each execution.

Please upload your python source code and a screen-shots of your three executions." one my assignment canvas show the coding

gleaming rover
#

"A Python-List is an object that contains multiple data items, you are expected to use the proper list functions to do the following activity.

Design a python application that prompts the user three times for three number values (integer or float) one by one. The application prints these three values and finally uses list functions to find and print the maximum and the minimum of these number values.

Please run the program three times and change the order of the integer values you enter such that the maximum number you enter is at different position at each execution.

Please upload your python source code and a screen-shots of your three executions." one my assignment canvas show the coding
@torpid pollen hi, I don’t mean to be rude, but:

  1. do you seriously expect someone to do your assignment for you?
  2. and that, without showing any work you’ve already done?
  3. this is a channel for discussion of the language. please read the description before indiscriminately spamming.
  4. try #❓|how-to-get-help.
fresh cargo
#

Question: What does sys.audit do?

#

I read the docs and it says "Raise an auditing event and trigger any active auditing hooks"

#

I guess my question is what audits are for? I'm not quite familiar with that terminology

gleaming rover
#

I guess my question is what audits are for? I'm not quite familiar with that terminology
@fresh cargo you mean what they are, or what they're for?

fresh cargo
#

Maybe both. I'm just not familiar with what auditing is

gleaming rover
#

Maybe both. I'm just not familiar with what auditing is
@fresh cargo basically...

#

you can register a function to be called when "certain things" happen.

#

"certain things" <- auditing events

#

"function to be called" <- auditing hook

#

why? for debugging, to do some advanced stuff, etc.

fresh cargo
#

Some event-driven programming stuff?

desert peak
#

eh, not quite

#

!d sys.audit

fallen slateBOT
#
sys.audit(event, *args)```
Raise an auditing event and trigger any active auditing hooks. *event* is a string identifying the event, and *args* may contain optional arguments with more information about the event. The number and types of arguments for a given event are considered a public and stable API and should not be modified between releases.

For example, one auditing event is named `os.chdir`. This event has one argument called *path* that will contain the requested new working directory.

[`sys.audit()`](#sys.audit "sys.audit") will call the existing auditing hooks, passing the event name and arguments, and will re-raise the first exception from any hook. In general, if an exception is raised, it should not be handled and the process should be terminated as quickly as possible. This allows hook implementations to decide how to respond to particular events: they can merely log the event or abort the operation by raising an exception.... [read more](https://docs.python.org/3/library/sys.html#sys.audit)
desert peak
#

it's referring to OS events, I believe.

gleaming rover
#

huh.

#

we're talking about this, right

fresh cargo
#

I think sys.audit is closely related to the Audits event table

desert peak
#

yes, and most of those events are OS-level events

#

syscalls, etc.

fresh cargo
#

Can I add events I want to audit or I'm limited to the ones in the table?

gleaming rover
#

maybe...half?

peak spoke
fresh cargo
#

Ah I think I got it

#

Thanks @gleaming rover @desert peak @peak spoke

boreal umbra
#

A few nights ago in voice, someone seemed to be making the argument that Python's use of third-party libraries is a weakness. I'm not sure if they were arguing that the language itself should have more functionality out of the box or if people should implement everything they need from the ground up or what. Do we have any idea what point they may have been trying to make?

desert peak
#

if I had to guess, too many libraries = too much foreign code in your project

safe hedge
#

I would guess the latter?

desert peak
#

I think Rust learned from what Python did and only brought the core into std while leaving the crates ecosystem to thrive instead

safe hedge
#

Basically you end up with a lot of dependencies, which, outside the bigger third-party libs could become deprecated/unmaintained at any point

desert peak
#

I think most of the stdlib is unmaintained 🤷

#

but at least the python org owns it

#

so I see the pro in that

peak spoke
#

It's a choice between doing it yourself or bringing in a third party module, which only helps as you still have the choice; and the amount of libs is one of the main upsides of the language

gleaming rover
#

A few nights ago in voice, someone seemed to be making the argument that Python's use of third-party libraries is a weakness. I'm not sure if they were arguing that the language itself should have more functionality out of the box or if people should implement everything they need from the ground up or what. Do we have any idea what point they may have been trying to make?
@boreal umbra I think the stdlib already has a ton of functionality

#

too much, in fact

desert peak
#

there are only like two packages I always bring into my project and they're pytest / ipython

gleaming rover
#

so I would be surprised if that was the argument

desert peak
#

I usually try to temper whether I need a dependency that might be in the stdlib since it has so much

peak spoke
#

Some older modules will probably be taken out of the stdlib, not sure what the state of the PEP is now

desert peak
#

it was pretty controversial

boreal umbra
#

@gleaming rover I don't really know what most stdlib packages are. Most of the ones that I regularly use are ones that I think of as an extension of the builtins, like itertools and pathlib.

#

it was pretty controversial
@desert peak I assume the argument was "muh batteries"?

flat gazelle
#

I can't really think of a language with a vaster stdlib than python, maybe java SE.

desert peak
#

the argument was the python organization took over some public projects and was now getting rid of that code without a community replacement @boreal umbra

peak spoke
#

!pep 594

fallen slateBOT
#
**PEP 594 - Removing dead batteries from the standard library**
Status

Draft

Created

20-May-2019

Type

Standards Track

gleaming rover
#

do we really need wave?

boreal umbra
#

!docs wave

fallen slateBOT
#

Source code: Lib/wave.py

The wave module provides a convenient interface to the WAV sound format. It does not support compression/decompression, but it does support mono/stereo.

The wave module defines the following function and exception:

boreal umbra
#

I could cope without it, but that stuff isn't me

flat gazelle
#

It was opted to keep since you can teach it to beginners, similar to turtle

desert peak
#

right, but python's thing is general purpose so there are people who do everything

flat gazelle
#

Which sounds super cool tbh

peak spoke
#

Looks like it has been a while and may need someone to revive the pep

desert peak
#

it's still talked about on the discourse

gleaming rover
#

I think it's fine to keep

#

but in the stdlib...?

#

shrug

peak spoke
#

Learning environments are commonly restricted

desert peak
#

the problem is - who maintains it once it leaves the stdlib?

gleaming rover
#

the same person

desert peak
#

do they move it to gitlab? github? who takes ownership of the code and package on pip?

gleaming rover
#

who normally maintains it

desert peak
#

good luck 🤷

gleaming rover
#

like the starting point is - should this be kept in the stdlib?

#

and if it's not...

#

if it's important enough, someone will pick it up or create an alternative

desert peak
#

core-js is pretty important to the js ecosystem, but there's no one lining up to take ownership of it.

#

without financial incentive, a lot of open source just dies

#

it's naïve to think otherwise

thorny geyser
#

no

signal tide
#

do we really need wave?
yes.

forest pawn
desert peak
#

what would you solve @forest pawn ?

forest pawn
#

personally, I forget the incantation (is it __name__ or is it __file__ for example) and I think that from a pedagogical perspective it's simpler to have a boolean for this check instead of the __name__ mangling.

I also think doing something like this would pave the way for removing the mangling in .... 5-10 years or whenever but maybe that's asking too much

desert peak
#

pyproject has been stable for a while and still doesn't see any use

safe hedge
#

We already have entrypoints for packages too

desert peak
#

entrypoints generated exes usually get flagged as malware for me

safe hedge
#

And __is_entrypoint__ implies that wherever that is true should be an entrypoint

#

i.e. how/where do you define the value of it?

empty girder
#

anybody here know how to make twitter bot

safe hedge
#

Wrong channel

empty girder
#

lol

#

really

safe hedge
#

Yes. This is not a help channel

empty girder
#

😇

safe hedge
raven ridge
#

it wouldn't be unreasonable to have an implicit py globals()["__main__"] = globals()["__name__"] == "__main__" That would let you shorten: py if __name__ == "__main__": To just: ```py
if main:

forest pawn
#

__is_entrypoint__ is probably the wrong name given entrypoints, but basically "a bool that replaces __name__ == "__main__"

desert peak
#

why not just have a __main__ dunder?

raven ridge
#

yeah, that's what I was proposing: to define __main__ to be the result of evaluating __name__ == "__main__"

safe hedge
#

But why is __name__ == "__main__" so bad?

#

Especially if all you're doing is aliasing it like @raven ridge did

gleaming rover
#

is __name__ used for anything else?

safe hedge
#

Internally you mean? I've used it in a extensible CLI thing I wrote

gleaming rover
#

more accurately

raven ridge
#

But why is __name__ == "__main__" so bad?
@safe hedge It's not that it's bad, it's that it's hard to remember unless you know Python's data model pretty well.

gleaming rover
#

how often do you use __name__ for anything but if __name__ == '__main__' (and getLogger(__name__) I guess)?

#

@safe hedge It's not that it's bad, it's that it's hard to remember unless you know Python's data model pretty well.
@raven ridge agreed. it's quite counterintuitive

safe hedge
#

@safe hedge It's not that it's bad, it's that it's hard to remember unless you know Python's data model pretty well.
@raven ridge Is it? Feels like one of those things which isn't obvious at first but after adding it to about 4/5 scripts its burned in your mind

#

Is remembering __name__ == "__main__" really massively more difficult than __main__ ?

raven ridge
#

is it?
From what I've heard, yes. I've seen people write if "__name__" == "__main__" before, and if __name__ == __main__, and both of those are badly wrong.

safe hedge
#

Also would having __main__ cause problems with the having __main__.py be the entrypoint when you do python -m module?

raven ridge
#

No, I don't think it would.

safe hedge
#

Since I assume there is something like import __main__ going on

raven ridge
#

import __main__ would still work. has to still work.

safe hedge
#

And then you've immediately masked the __main__ variable though...

raven ridge
#

if you assign it to that namespace, sure.

#

to understand why if __name__ == "__main__" works, you need to know a few non-obvious facts:

  1. __name__ is a magic global variable that stores the name that the current module was implemented with
  2. For the first module that the interpreter started running, it's instead set to the string "__main__"
    That's a fair amount of magic needed in order to do something that sounds relatively simple: do something only when run as a script, and not when imported.
#

and it's pretty hard to remember that if you can't contextualize it. (I've also seen people try "if __name__ == "main" now that I think of it...)

safe hedge
#

Or you just learn anything inside if __name__ == "__main__": runs when the script is called directly

#

Which is how I learned

#

I feel like you only make those mistakes one or two times whilst starting out

raven ridge
#

sure - this would be a thing that lowers the learning curve for people who are starting out. One less completely opaque magic incantation that doesn't make any sense and which they can't put in context.

safe hedge
#

I guess the question is how much of why do you need to understand to grasp what something does

raven ridge
#

the question shouldn't be "is if __name__ == "__main__" hard to remember", it should be "is it hard to learn". I'd argue that it is.

safe hedge
#

Are they not really the same thing here though

gleaming rover
#

consider also that

#

most people don't encounter dunder anything

#

until classes

#

and it looks weird af

safe hedge
#

The barrier to using them is "can you remember it and what it does"

gleaming rover
#

even more so to someone who's new

safe hedge
#

You literally don't have to understand the how to implement it

gleaming rover
#

which adds to the confusion of if __name__ == '__main__'

raven ridge
#

The barrier to using them is "can you remember it and what it does"
OK, let's take that as the barrier - can we agree that if __main__ would be easier to remember than if __name__ == "__main__" ?

safe hedge
#

Erm. Maybe? It's like 12 extra chars though

gleaming rover
#

it's not just the number of characters

#

but also the concept

raven ridge
#

yes - weird characters, with strange punctuation, that is hard to remember devoid of the context.

safe hedge
#

Maybe it's the way I learn, but I just committed it to memory through use long before I understood what it was doing

gleaming rover
#

okay imagine this

#

what if

safe hedge
#

So the concept was irrelevant

gleaming rover
#

for element in iterable was instead __divide__ iterable __into__ element

#

🥴

safe hedge
#

I'm not sure thats a fair comparison

gleaming rover
#

it's not, not exactly

#

but the points I want to make are:

  1. syntax matters
  2. sometimes it's not a question of "why?", but "why not?"
safe hedge
#

I just don't think an __main__ is all that much clearer honestly

raven ridge
#

I'm not sure thats a fair comparison
@safe hedge well, there is a fair comparison there, actually. What if you needed to call iter() on the iterable yourself, instead of for doing it implicitly?

#

for does that for you. People who know Python know that. It's only 6 extra characters.

gleaming rover
#

I just don't think an __main__ is all that much clearer honestly
@safe hedge I do think it is.

safe hedge
#

Like how does __main__ convey that it's true if the script is run directly

gleaming rover
#

"if this is the main program (the script is being run, as opposed to being imported)"

#

okay

#

get ready for a mega radical proposal

#

WHAT IF

#

it was if main()

safe hedge
#

Haha

raven ridge
#

that would break quite a lot of backwards compatibility.

gleaming rover
#

I mean, we have id, exec, eval, and memoryview in the global namespace

#

🤷‍♂️

safe hedge
#

I nearly said why not make it a non-dunder

gleaming rover
#

yup but let's just say

#

hypothetically backward compatibility issues aren't present

#

would that be nice?

safe hedge
#

if mainscript

#

if main_module

gleaming rover
#

if mainModule

safe hedge
#

Get outta here with that camelCase

#

FILTH

gleaming rover
#

if (mainModule) {

raven ridge
#

as far as I can see... A new variable that covers the most common case is entirely backwards compatible, as long as it's allowed to be reassigned. It's certainly more memorable (14 fewer characters to memorize!), and it'd be easy to implement.

#

if you did do import __main__, the __main__ global variable would be overwritten, but that's what you expect and want, so... 🤷

#

arguably the real problem here is that this is an advanced thing that people should rarely need to do. You need if __name__ == "__main__" in the case where you want a single file to both be importable as a module and runnable as a script, and do different things in each of those cases. That's not actually a very common need, and people overuse if __name__ == "__main__" in places where they don't actually need it

safe hedge
#

That is a fair assessment

forest pawn
#

The problem with the existing comparison, beyond “longer” (which I don’t think is a strong argument) is that somehow the “did I point python directly to this file to run it” question is answered by “did Python decide to mangle the name atttibute”.

Now name is sometimes used for logging but otherwise it’s one of those “advanced python” things that small scripts aren’t really messing with. And on top of that the name behavior in general fails the “don’t do magical stuff if you can avoid it” test.

So there’s both a sort a semantically weirdness of doing X to figure out Y instead of just being provided Y, and it had infected a global with some odd behavior

#

Buuuuut I recognize there’s both a lot of inertia and it’s not the biggest issue, so I’m not super tempted to introduce something comtroversial for such a marginal gain. Just feels like not how things would be tackled if this were happening today.

raven ridge
#

it's worth a thread on python-ideas, I think. __main__ = __name__ == "__main__" would be, as far as I can tell, completely backwards compatible and pretty trivial to implement.

#

it might get some inertia if it's proposed.

#

it's definitely less invasive than the change PEP 299 proposed.

#

and yeah - there's inertia for what exists today, but the proposal wouldn't make the old way stop working - it'd just introduce a new, simpler way. Not unlike what happened for super()

deft pagoda
#

is it not a common need? I feel like there're little tests I put at the bottom of a lot of my files meant for imports

#

i'm pretty sure i even put if __name__ == in files called __main__ because of the habit of it

raven ridge
#

I feel like there're little tests I put at the bottom of a lot of my files meant for imports
I'd sooner recommend pytest or doctest to someone who isn't already in that habit.

deft pagoda
#

i don't know what that is and i don't want to do more than little tests at the bottom of my file

raven ridge
#

blink

deft pagoda
#

i feel like i'm already doing the simplest thing possible

raven ridge
#

doctest is approximately equally simple.

deft pagoda
#

how is it equally simple if i need to learn another module

#

and they just put the test at the bottom of the file in the example anyway

raven ridge
#

there's not much to learn. For the most part, you can copy-paste from repls into your docstrings, and those become tests.

#

and they just put the test at the bottom of the file in the example anyway
@deft pagoda true - but you don't need to, you can also run doctest from the command line, with python -m doctest

deft pagoda
#

not needed for my use cases

#

which are small personal projects

raven ridge
#

small tests at the bottom of an importable module is fine, in simple cases. It doesn't scale very well, though. Like, you can't easily hook it into a CI system that runs all of your tests and lets you know if a change breaks any of them. You can't easily run all the tests across an entire package.

#

And it isn't what I'd recommend people do, since it's not really any easier to get started with than pytest is, and it eventually hits a scaling problem. Though it does work OK up until you hit the point of multi-module packages.

#

pytest, in a nutshell, is just: you write a file called test_foo.py, you put a function called def test_something() in it, and inside of that you make whatever assertions you want to make using assert. You run it with pytest test_foo.py, or pytest . to run all test_*.py in the current directory.

#

if you have a couple different tests you want to run, you have multiple def test_something_else() functions.

#

pytest isn't built into the stdlib like doctest and unittest are - but pytest is lighter weight and easier to start with than unittest, IMHO

deft pagoda
#

my tests are different than that --- like running a toy kivy app with only the widget implemented in the file

raven ridge
#

so you don't mean automated testing, you mean a manual, interactive test.

deft pagoda
#

for the most part

#

i've never done automated testing

raven ridge
#

ok. in that case, __name__ == ... is reasonable enough.

#

(you threw me because that isn't what I would call a test, but I'm with you that that's a reasonable use of checking __name__)

deft pagoda
#

there's this weird operator in ponylang .> that I've never seen before --- it calls a method of a class then returns the class as in:

my_dog = Dog() .> bark()
#

i wonder if there's ever been a similar operator proposed for python

boreal umbra
#

@deft pagoda so bark is only being called for it's side effects?

peak spoke
#

that does sound a lot like bark should just be a part of the constructor somewhere

deft pagoda
#

yeah, but you could do other things with .>

#

like:

class MySet:
    def copy_add(self, item):
        """Return a new copy of self with item added to it."""
        return self.copy() .> add(item)
pliant tusk
#

you can sort of do this with := ie ```py
(my_dog := Dog()).bark()

deft pagoda
#

yeah, it's just a small convenience, i thought it was a neat operator in any case

safe hedge
#

The problem with the existing comparison, beyond “longer” (which I don’t think is a strong argument) is that somehow the “did I point python directly to this file to run it” question is answered by “did Python decide to mangle the name atttibute”.

Now name is sometimes used for logging but otherwise it’s one of those “advanced python” things that small scripts aren’t really messing with. And on top of that the name behavior in general fails the “don’t do magical stuff if you can avoid it” test.

So there’s both a sort a semantically weirdness of doing X to figure out Y instead of just being provided Y, and it had infected a global with some odd behavior
@forest pawn your issue seems to be with Python setting __name__ to “__main__” but i don’t think that is changing anytime soon so all this just obfuscates that fact further

#

And as @raven ridge pointed out if a script is small-time enough to where the person writing it is unfamiliar with the __name__ principles then they probably don’t really need the behaviour, since it’s meant mainly for code that can be run as a module or a script

raven ridge
#

I've just sent a message to python-ideas proposing it. We'll see what people think.

gritty hollow
#

any django experts?

undone hare
boreal umbra
#

@raven ridge self doxed

undone hare
#

I’ve proposed that, like, 3 or 4 months ago lol

#

But it was rejected

raven ridge
#

lol whoops. I don't follow the mailing list actively, heh

desert peak
#

at some point, you stop caring about hiding your identity

#

a lot of online presence depends on your identity, especially in open source if you want to turn that into professional representation

raven ridge
#

I meant "whoops" about re-proposing something that has already been suggested. It's never been hard to tie me to my email address, or real name.

#

Doesn't worry or bother me.

#

Hell, my name is rare, it's probably not tough to find my IRL address.

feral cedar
#

I'll visit you 👀

raven ridge
#

Your pfp makes that so threatening 😂

grave jolt
#

I'll burn down your refrigerator

#

*kitten in a santa hat plays with ducklings*

desert peak
#

something that inspired the "stop caring about being anonymous" to me is that usernames are hard to come up with and remember and others can steal them from you depending on the platform (I'm getting old)

raven ridge
#

I try not to be an asshole online. Hopefully I'm more likely to get beer in the mail than a bomb. 🤷‍♂️

desert peak
#

twitter was a mistake for mankind. I agree with your sentiment

#

what was the feature you proposed anyways? I missed the context

undone hare
#

Something else than __name__ == '__main__'

desert peak
#

ah

undone hare
#

<@&267629731250176001>

grave jolt
#

!tempban @brisk mantle 14d posting NSFW off-topic gifs

fallen slateBOT
#

:x: According to my records, this user already has a ban infraction. See infraction #19029.

desert peak
#

time for that pban

muted crane
#

!p 448

fallen slateBOT
#
**PEP 448 - Additional Unpacking Generalizations**
Status

Final

Python-Version

3.5

Created

29-Jun-2013

Type

Standards Track

muted crane
#

So, how does PEP 448 work?

#

How does dictionary unpacking work and why do we need it?

#

Sounds a bit complicated in my opinion

#

It seems as if we are merging dictionaries

flat gazelle
#

something very common is that you get a dict like

{'name': 'John Doe', 'age': 21, 'height': 163}
```, and you want to get the 3 things out of it into separate variables
#

unpacking makes that a lot easier.

muted crane
#

It's just that it seems to look like it merges dictionaries or seems too hard to notice when reading the code the first time

#

Difficult to understand the syntax

#

This was an issue mentioned in the PEP

feral cedar
flat gazelle
#

oh wait, that is a different PEP. don't mind me

muted crane
#

So, they picked this syntax to prevent line noise which affects readability drastically

feral cedar
#

yeah, it's much easier to unpack things now

muted crane
#

Hmmm, I see

knotty sequoia
#

can someone help me with this code

#

it says invalid syntax and i dont know what is wrong with it

sour obsidian
#

simple

flat gazelle
floral zodiac
#

@knotty sequoia u didnt insert colon after if statement

desert peak
#

Just a thing that happened, might apply here, Guido works for MSFT now

feral cedar
#

woah

prisma cypress
#

Hey people not sure if this is the right channel for this.

Do you use dotenv to manage environment secrets? Or do you use something else?

boreal umbra
prisma cypress
#

ty ty.

desert peak
#

with python 2 being EOL finally, does tox provide much benefit anymore?

true ridge
#

From the perspective of a library maintainer, indeed! Python 3.6, 3.7, 3.8 and 3.9 have still some differences. Especially if you are used to work with the latest version in the matrix, you might sometimes forget to give up from certain habits.

desert peak
#

I'd suspect you just stick to a specific version when developing the library

true ridge
#

While doing changes, I test with the version that is installed in my environment. After the suite passes, I'll just execute tox to verify it works on all 4 versions (and pypy).

desert peak
#

does tox handle the version installation and such or do you need to set up your environment yourself?

true ridge
#

No, AFAIK it uses virtualenv under the hood so that you'd need have the environments in your system already.

magic python
#

How does that workflow look? You have 4 envs for a single package, and each one has a different python version?

true ridge
#

Yes.

safe hedge
#

But it was rejected
@undone hare Can I ask why?

raven ridge
safe hedge
#

I'll give it a read

#

!pep 299

fallen slateBOT
#
**PEP 299 - Special __main__() function in modules**
Status

Rejected

Python-Version

2.3

Created

12-Aug-2002

Type

Standards Track

spark magnet
#

@desert peak why would tox be obsolete just because you don't use python 2?

desert peak
#

because I have yet to see any breaking changes in supported versions of Python @spark magnet

#

so the thought would be, just use the oldest supported version and only use that for development of your package

spark magnet
#

@desert peak i guess that could be a strategy. it's safer to run on many versions.

#

You might want to test on pypy, for example.

desert peak
#

shouldn't pypy/cpython be equivalent?

spark magnet
#

what does the word "should" mean in that sentence? 🙂

#

yes, they should 🙂

desert peak
#

like, they have a spec, and they implement that spec equally

#

I have no idea what defines Python now that I think about it

#

if we're talking about the base language (no stdlib), there surely isn't that much to it, right?

spark magnet
#

it depends how detailed you want to get. PyPy closes files at different times, for example.

desert peak
#

side-note: I was looking into why I use pytest-cov and I remembered; generating a bunch of different reports with coverage alone is a PITA

spark magnet
#

What is the pain? You run a number of commands.

desert peak
#

for the purpose of sonarqube consumption, I'd have to invocate coverage some 3-4 different times

spark magnet
#

why is that hard?

desert peak
#

tossing that into a config file is much easier

#

it's not hard, but it's more places I have to look to ensure my configuration is right

spark magnet
#

i don't understand. we have .sh, Make, tox, etc, for running commands. why cram it into pytest?

desert peak
#

I like having a centralized place to look at config

#

because my environment sucks. I develop on a windows 7 box with py38 while my pipeline & runtime are py37 on RHEL, and then on Ubuntu

spark magnet
#

sounds like tox would be mighty handy....

desert peak
#

if I could even get it into the pipeline lol

#

does tox provide the python versions?

spark magnet
#

no, you hav to have those installed

desert peak
#

yeah, that's my first non-starter

#

I'd have to go through a multi-month procurement cycle and hope the other team responsible is engaged

spark magnet
#

avoiding tox won't get you the python versions.

sacred yew
#

plus theres a bunch of breaking changes even between "minor" versions

spark magnet
#

@desert peak how do you get python versions now?

sacred yew
#

why semver is better

desert peak
#

@spark magnet we have a software store that deploys whatever is supported through SCCM. For Linux? pray that the greybeards actually packaged something

spark magnet
#

ok, so you have python versions. How is that a tox dealbreaker?

#

i get the feeling there's a tox misconception here

desert peak
#

because I can only pick one python version for my pipeline

spark magnet
#

ok. where's the problem?

desert peak
#

I guess I'm not sure what problem you see I have that tox would solve

spark magnet
#

you said you didn't want to deal with multiple commands. tox.ini can be the place to put those commands.

desert peak
#

oh, gotcha

#

now I follow. I'll have to check it out

desert peak
#

@spark magnet so does it take your list of envs and run the list of commands against each environment?

spark magnet
#

that's the simplest form of execution, yes. it's very configurable.

raven ridge
#

why semver is better
@sacred yew 🤷 If Python used semver, it would just use a new major version on every release instead of a new minor version. The issue isn't the versioning system, it's the decision to allow breaking changes on any release.

unkempt rock
#

anyone wanna talk about something

#

im bored

#

also i need 7 more messages to get voice verified

gleaming rover
#

anyone wanna talk about something
@unkempt rock I hope it's related to the language

#

because this is a channel for language discussion

unkempt rock
#

it is

#

?

gleaming rover
#

it's literally in the channel description.

unkempt rock
#

oh-

#

where should i conversate then

gleaming rover
#

also i need 7 more messages to get voice verified
@unkempt rock I believe it's also against the rules to send messages for the sake of having more messages so you get verified...which kind of looks like what you're doing right now.

#

!ot

fallen slateBOT
unkempt rock
#

oh

gleaming rover
#

just my two cents

unkempt rock
#

well i mean im also trying to actually have a convo

#

im not just typing to have messages

#

i was just throwing that out there incase anyone wanted to vc

gleaming rover
#

sure, go ahead, but not here...because as I said, this channel is for discussion of the Python language...

compact scarab
#

i swear that one time someone showed me a trick about expanding arguments to set a few variables.. something like
var1, *, var2 = *something that has more than 3 return values
and it worked somehow, but i cant get it to now :\

#

anyone know?

pliant tusk
#

@compact scarab i assume you want to throw away the inner values?

compact scarab
#

yep exactly

pliant tusk
#

var1, *_, var2 = something

compact scarab
#

oh snap thats the syntax? 👀

pliant tusk
#

it places all of the inner values into _

north root
#

oops, meant to ctrl k

compact scarab
#

dope, worked! thank you @pliant tusk

pliant tusk
#

no prob

undone hare
#

@safe hedge sorry for my late reply, but here is the thread https://discuss.python.org/t/add-an-imported-flag-to-avoid-the-use-of-name-main/4141

#

It boiled down to two things : the __main__ module is actually imported so this flag wouldn't make sense, and if you want to keep retro compatibility in your code you'll have to write something even longer to integrate the new flag

safe hedge
#

Ok yeah that got shot down pretty sharpish

#

The main module is imported (under the name __main__, precisely).
This seems key I guess

undone hare
#

Yeah, they made pretty fair arguments honestly

raven ridge
#

I don't find either of those arguments terribly compelling. One was merely about the name of the flag, rather than its worth, and the other is a valid argument against ever introducing any feature that simplifies something that is already possible.

#

Yes, there will be a period where the new feature is not ubiquitously supported and you'll need to avoid using it in code intended to be portable for older interpreters. Just like f-strings, and async def coroutines, and data classes, and the walrus operator, and positional only arguments...

wide shuttle
#

@unkempt rock You could try it in #bot-commands. If you think you've found something that you probably shouldn't be able to, please do get in touch. We won't be mad if you find something, although do be a considerate in actually exploiting it.

unkempt rock
#

hello !

cloud crypt
#

hello

hasty portal
#

hello

true ridge
#

I started to dislike the look of 'bare returns'. Just not dealing with them, I do my best to avoid early exits (even that means I have to indent redundantly a couple of levels). At worst, I'd go with return None. Does anyone have a similiar (or counter) opinions on this?

peak spoke
#

I usually go with return None, but don't really go out of my way to avoid early exits

sacred yew
#

if the function normally returns a value, then i usually go with return None

#

otherwise just return

wide shuttle
#

I think you should consider readability. I don't mind "bare" returns myself and I think that it sometimes very clearly follows the logic of a function, which makes it a logical and readable part of the routine logic.

#

However, I forgot the name (structured programming?) states that a function should only have one return and it should be at the end of the function

true ridge
#

By the way, what I mean by 'avoiding early returns' is writing the first one as the second one;

def some_func(item):
    if not isinstance(item):
        return
    
    result = do_something(item)
    if not result.flag | other:
        return
    
    for item in result:
        print(item)

def some_func(item):
    if isinstance(item):
        result = do_something(item)
        if result.flag | other:
           for item in result:
               print(item)
wide shuttle
#

I like the first one more than the second one

#

I feel like you need to do a lot of gymnastics just to get that only (implicit) return at the end of your function

spring bronze
#

High cyclomatic complexity

wide shuttle
#

This specific example isn't to bad, but this function is relatively short

true ridge
#

I feel like you need to do a lot of gymnastics just to get that only (implicit) return at the end of your function
@wide shuttle Unfortunately, yes. It gets more and more complex when forcefully gather everything under a roof of a single branch.

wide shuttle
#

I like the "if the input is not this, we can stop, no need to scan the function for a maybe use somewhere"

sacred tinsel
#

I find myself using early returns more and more

#

I strongly prefer it to deep indentation

spring bronze
#

Yes

hasty portal
#

Can i share github project link here?

boreal umbra
#

@hasty portal not in this particular channel. You can talk about your projects in relevant topical channels, but reddit is probably a better platform because discussion isn't limited to who sees a message before it's in scrollback territory.

hasty portal
#

Okay thanks

gleaming rover
#

I started to dislike the look of 'bare returns'. Just not dealing with them, I do my best to avoid early exits (even that means I have to indent redundantly a couple of levels). At worst, I'd go with return None. Does anyone have a similiar (or counter) opinions on this?
@true ridge those are called guard clauses I believe

#

and well like if you look at functional languages there basically aren’t even return statements

#

which I am actually quite a fan of

#

knowing a function’s return value is always at the end adds value

true ridge
#

Yeah, and actualy can be quite useful for keeping the function lineer.

gleaming rover
#

and I do things in Python like use if expressions in place of if statements

#

to achieve “one return”

#

that said

#

there are syntactic constructs that are just missing

true ridge
#

Like a special exception (Release) raised if the guard fails ensure isinstance(a, int) that would pop out from the current context and switch the upper one on the stack

gleaming rover
#

to achieve that effect as easily as you can in other languages

#

for example, pattern matching expressions

#

or an explicit option type

grave jolt
#

well, there is an option type --None vs not None, it's just that there aren't any built-in utilities for that

raven ridge
#

I optimize for readability. Sometimes early returns are more readable, sometimes less.

grave jolt
#

I think this:

def abs(x: int) -> int:
    if x >= 0:
        return x
    else:
        return -x
``` makes more sense than this:
```py
def abs(x: int) -> int:
    if x >= 0:
        return x
    return -x

because the two branches are 'equally likely', or rather none of them is more special than the other

#

unlike here (contrived example):

def filter(iterable, fn=None):
    if fn is None:
        return fn(iterable, bool)

    result = []
    for x in iterable:
        if fn(x):
            result.append(x)
    return result
``` or maybe even:
```py
def filter(iterable, fn=None):
    if fn is None:
        yield from fn(iterable, bool)
        return

    for x in iterable:
        if fn(x):
            yield x
#

but it's kind of vague

gleaming rover
#

well, there is an option type --None vs not None, it's just that there aren't any built-in utilities for that
@grave jolt it's not explicit

#

just like a function that returns String in Java really means "returns String or null"

grave jolt
#

Optional[T] is pretty explicit to me 🙂

gleaming rover
#

like there is no distinction between T and Optional[T]

#

Optional[T] is pretty explicit to me 🙂
@grave jolt yes, that's my point

#

Optional[T] isn't actually a thing beyond T | None

grave jolt
#

like there is no distinction between T and Optional[T]
there is, a typechecker (if configured correctly) will yell at you if you assume that an Optional is not None

gleaming rover
#

yes, there is

#

but what I'm saying is more like

#

it's just an untagged union type (as opposed to a sum type)

grave jolt
#

you mean, the successful case isn't marked as Just(T) or Some(T)?

#

well, true

gleaming rover
#

yeah and the machinery is missing

#

e.g. map or pattern matching

grave jolt
tawdry gulch
#

That.. is a funny error though especially if it is a professional library

grave jolt
#

@final scroll We don't allow advertising on this server. You can share your article if it's relevant to a particular discussion (e.g. when someone wants to know how decorators work (although there's already a good article on realpython.com, not sure if more are needed)), but don't just dump links to your resources here.

final scroll
#

Sure

boreal umbra
#

@echo harness your proposed syntax restricts functionality because for any (f on someSeq), there has to be a method f.__call__ that does exactly what is wanted. Whereas the status quo lets you do any expression.

#

I don't really like the look of (x for x in y if f(x)), but you have filter for that.

gleaming rover
#

^

#
list(map(f, iterable))
[f on iterable]

list(filter(f, iterable))
(_ on iterable if f)

not that much of a difference IMO

#

I do think it's more readable in the map case

#

but not really sure if it's worth the tradeoff (new syntax)

#

and in the filter case...that changes the meaning of if

#

because there's implicit function application

mint forge
#

what does | this syntax mean in python?

inner acorn
#

it is a bitwise opperator, means 'or'

#

if x>y | a>b :
would read as if either x is greater than y or a is greater than b

mint forge
#

Oh i see

sacred yew
#

n

raven ridge
#

That happens to work, but using bitwise operators for truth testing is unusual and can lead to bugs.

sacred yew
#

don't use bitwise for that

#

bitwise ops are for operations based on bits

#

@mint forge @inner acorn

#

bitwise or means for each bit, take the or of the 2 corresponding bits of the 2 operands

radiant garden
#

if x>y | a>b :
would read as if either x is greater than y or a is greater than b
@inner acorn Shouldn't that evaluate to x > (y|a) and (y|a) > b?

sacred yew
#

for instance (0b100 | 0b010) == 0b110

#

same thing for bitwise and, not and xor

#

plus bitwise ops have really weird operator precedence

mint forge
#

wait what?

raven ridge
#

@inner acorn Shouldn't that evaluate to x > (y|a) and (y|a) > b?
@radiant garden ah, yes it would. Like I said, leads to bugs 😄

sacred yew
#

use logical or/and for bools

mint forge
#

ik, i wont use that but like what does that mean in python?
or?

sacred yew
#

You know how logical and/or applies to "single bits"?

#

where true==1 and false==0

mint forge
#

You know how logical and/or applies to "single bits"?
@sacred yew i do not

#

wdym by "single bits"?

north root
#

0s and 1s

mint forge
#

oh

north root
#

binary

sacred yew
#

so true or false

#

is 1 or 0

#

and the result is always a single bit(assuming all bools)

mint forge
#

I see, but how does that relate with my main questions?

raven ridge
#

!e ```python
print(3|7)
print(3&7)

fallen slateBOT
#

@raven ridge :white_check_mark: Your eval job has completed with return code 0.

001 | 7
002 | 3
sacred yew
#

Ok

#

so bitwis3 or extends that to all integers

raven ridge
#

So:
7 in binary is 111
3 in binary is 011
| finds the number where anything that's 1 in either is 1 in the result. So 111, 7.
& finds the number where anything that's 0 in either is 0 in the result. So, 011, 3

sacred yew
#

by doing an or for each bit in a number's binary representation

mint forge
#

ohh

#

i see

#

thx

raven ridge
#

12 and 10 make a more interesting example.

#

!e ```py
print(12|10)
print(12&10)

fallen slateBOT
#

@raven ridge :white_check_mark: Your eval job has completed with return code 0.

001 | 14
002 | 8
mint forge
#

@raven ridge how do u know what they are in binary?

sacred yew
#

bin(7)

north root
#

you can count it out

raven ridge
#

That's because:
12 is 1100 in binary
8 is 1010 in binary
| finds the number where anything that's 1 in either is 1 in the result. So, 1110, 14
& finds the number where anything that's 0 in either is 0 in the result. So, 1000, 8

mint forge
#

hmmm

raven ridge
#

In base 10, the system you're used to, a number like 623 means "three and two tens and 6 hundreds"

#

In binary, a number like "1110" means "zero and one two and one four and one eight"

#

and 2 + 4 + 8 is 14, so 1110 in base 2 is 14 in base 10

north root
#

so for 7:

4 2 1
1 1 1

4+2+1=7

for 3:

4 2 1
0 1 1

2+1=3

sacred yew
#

tbh bitwise ops aren't used that commonly now

north root
#

how about the square root function from doom though

sacred yew
#

since you can use a set to represent flags

raven ridge
#

they're used commonly in some areas, but not everywhere.

sacred yew
#

I think I've only used them for some crypto and bitwise flags

raven ridge
#

Yeah. The place you're most likely to see them is crypto and implementation of network protocols or manual serialization.

north root
#

Discord uses it for their permissions system

sacred yew
#

aka the only places where bits matter anymore

north root
#

another common application

sacred yew
#

yeah bitwise flags

#

It really sucks that they have such an awful operator precedence

#

thanks to c

raven ridge
#

that doesn't actually use any bitwise ops per se. I guess i >> 2 but that's just a way of writing i / 2 for stupid compilers

signal tide
#

is it not a cheaper way of doing it?

raven ridge
#

not with a modern optimizing compiler, no

signal tide
#

ik the article mentions how it truncates the remainder, idk if that's important or not

#

there's too many parenthesises in the text to tell

raven ridge
signal tide
#

actually performing the shift doesn't call it tho?

raven ridge
#

that's got a sar operation instead, which is... also a right shift.

sacred yew
#

it's c

raven ridge
#

throwing -Og in the "Compiler options..." box in the top right gives nicer assembly output.

sacred yew
#

Integer division always truncatrs

#

just like py2

signal tide
#

-0g made it fail

raven ridge
#

capital oh, not zero

signal tide
#

smh

raven ridge
#

capital o is the optimization level flag, and g is "optimize for debugging"

signal tide
#

regardless it still looks cheaper to do a right shift

#

there's a very high possibility idk what I'm talking about tho

raven ridge
#

ah, yes - because I had a bug there.

#

/4 and >>2 generate exactly the same assembly. Likewise for /2 and >>1

#

(the bug the first time was using signed rather than unsigned integers)

#

we've wandered off topic, though - feel free to ping me in an OT channel if you'd like

signal tide
#

I see now, I'll ping you when I have braincells to spare

nocturne cloud
#

Hi, I have some questions about the google colab, It is easy to run a Neural Network on colab with a TPU?

swift imp
#

>> and << should only be used to perform multiplication and division of integers by 2. I mean you can do floats too buts a lot more tricky. There's a famous computation some guy did for a game where he performs a super fast 1/✓2 calculation for vectors by utilizing bit shifting and approximating it

mystic cargo
nocturne cloud
#

I didn't see the channel sorry

unkempt rock
#

anyone know how to fix this weird word wrap on notepad?

feral cedar
#

although, i believe there is a word wrap option in format or something

bronze holly
#

Might also be a CRLF vs. LF issue - see https://en.wikipedia.org/wiki/Newline#Representation

Newline (frequently called line ending, end of line (EOL), line feed, or line break) is a control character or sequence of control characters in a character encoding specification (e.g. ASCII or EBCDIC) that is used to signify the end of a line of text and the start of a new o...

spice pecan
#

judging by the top bar, it's windows 8 at least, the default notepad was capable of handling both CRLF and LF at that point IIRC

prisma cypress
#

Hey all, I think my pyenv and settings are all messed up. I was wondering if I can run couple things by you guys.

#

I'm on osx, and it has its own python.

I tried not to use python installed from homebrew and instead do everything do pyenv.

#

But typing pip into command line shows something like

~ pip
pyenv: pip: command not found
#

Brew has python@3.8 and python@3.9 installed. I think other packages depend on it.

#

I think I figured it out. I think there's no pip installed with the system Python and by linking to it, there's no pip.

muted crane
#

First of all: this is unrelated to the topic, reread the description

#

Second of all: Good job!

unkempt rock
#

@raven ridge Sorry for the unnecessary ping, I was looking back at the code you wrote and saw that you did id(obj) + 32, and if I do it without 32 it doesn't work. Do you mind explaining why you did that?

raven ridge
#

(I told you, it depends on lots of fragile implementation details)

unkempt rock
#

Ah, interesting. Is there any way for me to start learning about this stuff other than just reading source code?

raven ridge
unkempt rock
#

Thank you

raven ridge
gusty lichen
#

Hi, I am not quite happy with the current state of timeit. Not allowing arguments for functions is something that really frustrates me. I would like to use timeit to make a quick check how performant my code is - especially with differing arguments - like testing different sorting algorithms for different sizes of an array. I have to make a workaround like this:
t = timeit.Timer(lambda: eratostones(limit))
or create a wrapper function just for a quick check on performance.
I would also like to have a median for fast functions - I know it is possible, but takes more time to set up

ipython's %timeit allows exactly for what I am asking. I can just write something like this:

%timeit sum(range(100))
>>>100000 loops, best of 3: 1.54 µs per loop

I ask myself why this is not used in pythons timeit - or if there may be a module that provides this functionality (not the % line magic, but something that is just shorter)

radiant garden
#

The command-line module is more useful for something like this. python3 -m timeit

#

within your code, timeit.timeit(str/callable) also works

#

you can pass in globals iirc

gusty lichen
radiant garden
#

globals={"limit":limit} to the fn call

#

you've got to pass everything from the external scope in manually

#

Or just: globals=globals()

gusty lichen
#

thats what I mean - it is possible, but I have to manually write extra code just for testing it with timeit
with ipython, I have my function that I could use in a prod environment, write %timeit in front of it and get the runtime

radiant garden
#

yeah no luck with that ig

gusty lichen
#

like, I made it callable with "wrapping it" in a lambda, but I still pollute the output.
Maybe a mistake on my side, but I dont know how to fix it.
https://hasteb.in/doyaziza.py

#

ipythons timeit just seems superior to me. I wonder if that is the case or if I am missing something crucial. Or it might just be superior.

tepid crater
#

how often does this whole library get used? https://pymotw.com/3/ I barely learned the function of random a few days ago.

sacred yew
#

you mean the entire stdlib?

tepid crater
#

yeah. my mind is blown. I have endless hours of information to read on. this is going to take more than 300 hours to master.

unkempt rock
#

Ehh, more like months

tepid crater
#

Ehh, more like months
@unkempt rock seriously. brb. lol.

raven ridge
#

trying to memorize the entire standard library isn't a great use of time. There's lots of things in it that are only useful in particular situations.

#

Start trying to build real programs, ask around for how other people would approach the problem, and learn the modules they point to.

tepid crater
#

trying to memorize the entire standard library isn't a great use of time. There's lots of things in it that are only useful in particular situations.
@raven ridge ah ok. thanks for the knowledge bomb!

humble geyser
#

?why?

smoky turret
#

You definitely do not need to memorize every function that exists, though I do find it both fun and informative to go through the module index every once in awhile to see whats available

#

difflib is a lesser known module, but really nice to have when you need it, for example

#

pathlib is way underutilized

unkempt rock
#

I have code that I want to get reviewed. If there is a channel or if someone wants to review it, please tell me

mint forge
sweet peak
#

hi when i want to generate a key value pairs into empty discitnors as dicto['value2']['value2'] = 123 it gives key error it is a bug

mint forge
radiant fulcrum
#

it probably isnt a bug

spark parcel
#

We’re discussing the implementation and differences between == and is for strings. Above is the relevant source code for the string eq method

#

I think it looks like it’s comparing the data of the strings (after ruling out obviously false things) and not the actual memory address, when checking for equality. Is this actually what the implementation is? I heard that it might actually be checking if the objects are the same in memory, which doesn’t quite make sense to me

sturdy timber
#

== would have to compare the data of the strings, as the memory address may be different even if they are the same

spark parcel
#

That’s what I had thought as well. Not sure why someone thought it would compare memory addresseslemon_thinking

spice pecan
#

It could technically compare the address first, because if both operands reference the same string in memory, there's no need to actually compare them

spark parcel
#
memcmp(PyUnicode_1BYTE_DATA(a), PyUnicode_1BYTE_DATA(b),
                 PyUnicode_GET_LENGTH(a) * PyUnicode_KIND(a)) == 0;

I don’t know enough c to interpret this function, but doesn’t it sound like memcmp would be comparing the memory addresses? This is part of the code I linked above

spice pecan
#

It compares the contents, yeah

spark parcel
#

Yeah. It could do that. I’m mostly wondering about the current implementation

spice pecan
#

The current implementation doesn't seem to check whether or not they're the same string during equality comparison

spark parcel
#

You mean by checking the memory address?

spice pecan
#

yeh

#

unless it's somewhere else

spark parcel
#

It should all be in the file I linked

#

Unless I’m completely lost in navigating the CPython source code

spice pecan
#

Oh wait, this one seems to be specifically for strings with colliding hashes

#

or not

spark parcel
#

The one I linked...?

spice pecan
#

no I'm just being slow, nvm

spark parcel
#

Hahah okay

spice pecan
#

I remember something about dictionaries that exclusively use interned strings for keys

#

CPython just checks the address in those cases IIRC

#

Perhaps that's what they were thinking about

spark parcel
#

Hmm... maybe

sturdy timber
#

if (left == right) is comparing the pointers, and returns True if the op is case Py_EQ

spark parcel
#

Hmm.. interesting

#

So it basically does str1 is str2 before going into the entire “are the values the same?” route?

spice pecan
#

Makes sense, it's a cheap check that can save lots of time for long strings

sturdy timber
#

Yep

#

If they aren't equal it goes on to the other check (the one you linked to)

    else if (op == Py_EQ || op == Py_NE) {
        result = unicode_compare_eq(left, right);
        result ^= (op == Py_NE);
        return PyBool_FromLong(result);
spark parcel
#

Yeah. It is very smart. As well as returning false directly if the string lengths aren’t equal

#

Aah, right. The check I linked starts off with doing a Unicode eq check

unkempt rock
#

Hello folks. I am attempting to turn a modest for loop into a one liner (I can't use reduce):

#
dispose = set()
    for index, item in enumerate(prosodies, 1):
        if item in dispose:
            return index
        dispose.add(item)
spark parcel
unkempt rock
#

... which basically finds the index of the first duplicate in a sequence.

#

I got to this: next(filter(lambda enumeration: enumeration[1] in dispose, map(lambda x: dispose.add(x[1]), enumerate(prosodies, 1))))[0]

sturdy timber
unkempt rock
#

This might be better in #esoteric-python if you're trying to make a one liner
@sturdy timber Alright, I will knock at their door. The idea is to bring CC (cyclomatic complexity) down to 1 ... so without using for loops, list comprehensions, etc.

sturdy timber
#

Sorry for moving you around so much 😅. Asking in the right place should increase your chance of getting an answer though

unkempt rock
#

@sturdy timber Thanks. I am not after efficiency in this case. Gains would be inconsequential. I am merely looking for an alternative syntax on one line, as I've done with other portions of my code. I'll ask the "esoteric" crowd.

grave jolt
#

@unkempt rock I'm pretty sure a giant one liner isn't going to reduce the complexity of the code.

#

maybe it will trick the CC calculation tool, but map(lambda x: dispose.add(x[1]), enumerate(prosodies, 1)) is no better, and maybe worse, than (dispose.add(x[1]) for x in enumerate(prosodies, 1))

unkempt rock
#

Thanks @grave jolt, I actually got it in the end, although I am not satisfied:

#
    dispose = set()

    # horrible hack to remain within dipose's scope and feed the return value to the filter
    def check_add(enumeration):
        check = enumeration[1] in dispose         
        dispose.add(enumeration[1])
        return check

    return next(filter(check_add, enumerate(prosodies, 1)))[0]
grave jolt
#

I think this version was the best

def index_of_first_duplicate(prosodies):
    dispose = set()
    for index, item in enumerate(prosodies):
        if item in dispose:
            return index
        dispose.add(item)
    return None
unkempt rock
#

Of course, I totally agree. But I have a long script whose CC I want to bring down to 1. So I am removing all loops, ifs, etc.

grave jolt
#

why are you doing that? 🤔

#

as an exercise?

unkempt rock
#

Self imposed exercise, to learn.

grave jolt
#

well, I think you'll only trick a CC computation tool -- I wouldn't say that a loop has more cyclomatic complexity than map with a side-effectful function

#

I mean, in Haskell there are no loops or if statements -- do Haskell programs all have CC of 1?

unkempt rock
#

Yes. But not using loops forces me to get more familiar with functional styles, map, filter and the lot. I am using Radon to calculate CC.

grave jolt
#

oh, okay

unkempt rock
#

Thanks though, @grave jolt.

radiant scroll
#

I'm storing a NxN matrix in a file (2D list) and I need a way to rotate it by 90 degrees, i.e.:
from:

1 2 3 4
5 6 7 8
9 0 0 0
1 1 1 1

you'd get:

1 9 5 1
1 0 6 2
1 0 7 3
1 0 8 4

This could be easy if I just loaded the list into a python list and did something like: list(zip(*reversed(lst)))
Problem is that this 2D list is way too big to load it whole into memory so that's not possible.

The way I'm storing this list is basically in "blocks" in which the matrix is flat, each block containing certain amount of data (let's call this amount b), so basically for the example above, with block size of 2 the stored list would look like this: [1, 2], [3, 4], [5, 6], [7, 8], [9, 0], [0, 0], [1, 1], [1, 1]

I need some meaningful way to rotate this list without loading too many blocks into memory.
The storing works in a way where the amount of data each block can contain (b) is known and n (size of matrix) is also known and it will always be a multiple of b

I figured I could just go through these elements, get the block they're in, read it, get the element from that block, store it and get the block in which the corresponding element number (after rotation) would be. Then just swap those and write them back. Problem is that this would make way too many calls to write and read (2xN^2) calls to read and another (2xN^2) for write, which would be way too slow. Is there a more meaningful way to do this than just going through every element, finding the rotate pos and swapping it directly?

mint forge
radiant scroll
#

alright, thanks

unkempt rock
#

Not sure if this is supposed to be here, but if it isn't I'll move it somewhere else.

#

But how would you type ctypes?

#

For example:

#
from typing import Union
from ctypes import *

def func(*pointers: ...):
    pass

#

I can't seem to find a way to make it generic

grave jolt
#

@unkempt rock you can probably get help in #esoteric-python, although it's not necessarily on topic there. You could just open a help channel

unkempt rock
#

Ok, I see

violet jetty
#

say there's something like zip is there a way to inspect how it works? like the underlying programming for it?

deep bramble
#

you could see the bytecode

#

with dis module

peak spoke
#

For how the builtins work you'll have to look into the C source they're implemented in

#

The bytecode will only contain a call instruction

deep bramble
violet jetty
#

i'm new to python. my intent here is to glance over something to get a better sense of the underlying logic of what i'm using.

#

so i used zip as an example. can you link to the file, subfolder, whatever, where i might find what i'm looking for at that repo? @deep bramble

deep bramble
#

well it's kind of hard since there isn't necessarely a specific place to look, but if you're looking for common objects, you could go here: https://github.com/python/cpython/tree/master/Objects which contains things like enumerate, or tuple objects

violet jetty
#

zip is a funciton iirc. is there not a location at which that is described?

peak spoke
violet jetty
#

okay i'll explore that. so what i'm reading there isn't python. is that correct? it's some other language? @peak spoke

spice pecan
#

It's C

deep bramble
#

it's code of python itself, which is written in C

violet jetty
#

ah okay. maybe i should take a C crash course.

#

thanks for your assistance.

true ridge
#

A couple of functions (like zip, all, any etc.) have ~similiar python implementation at the docs, for people who intend to comprehend the underlying implementation

noble mesa
#

what's the advantage of using nginx with django?

#

serving static files and routing?

unkempt rock
#

So im making a class with __add__ the thing is the other operand should be anything which can be added, so I can add it into my instance, how do I implement it? typing.SupportsFloat or should I use the abc in numbers i dont know

#

i would like to be able to do instance + 1 instance + 2.3 instance + decimal.Decimal('2.3') instance + fractions.Fraction(23, 10) for example

pliant tusk
#

You should be able to just define a def __add__(self, arg)

unkempt rock
#

yeah I can

#

but i need an abc for the NotImplemented part

#

What's the correct abc here

spice pecan
#

numbers.Number I'd assume

raven ridge
#

str has __add__ but isn't a numbers.Number.

sacred yew
unkempt rock
#

Oh I only want numbers that can be added

raven ridge
#

Then numbers.Number sounds right.

unkempt rock
#

Sorry for the image , but what is (*args) here

#

What not simply super().init()

#

( program is for creating a sequence of own where major features from type -list)

cloud crypt
#

*args is a variadic number of positional arguments, collected into a tuple

signal tide
#

^ you're initializing List with the args from init'ing CounterList

#

oh would that initialize a list with args as the items?

cloud crypt
#
>>> def check(*args) -> None:
...     print(args)
>>> check(0)
(0,)
>>> check(13, 42)
(13, 42)```
#

no

#
>>> def add(a: int, b: int) -> int:
...     return a + b
>>> args = (13, 42)
>>> add(*args)
55``` `*` in the call is unpacking an iterable object
safe hedge
#

It's just there to act as a pass-through right

cloud crypt
#

so in the end super().__init__(*args) will proceed to make CounterList(whatever) do list(whatever)

#

also I don’t think super(CounterList, self) is necessary and you could use just super() instead

signal tide
#

that's what I mean, is there a redefinition of list, or will it do list(*args) -> [*args]?

cloud crypt
#

what do you mean redefinition

signal tide
#

I mean the parent class is list which is a builtin

cloud crypt
#

__init__ of the list takes only one argument, an iterable object

#

and that’s what is called

#

built-in objects are no special in a sense of OOP, really

signal tide
#

I've just never seen a builtin being called like that

raven ridge
#

super() may be list, but not necessarily.

safe hedge
cloud crypt
#

well super().__getitem__ will be the top __getitem__ in the MRO

#

and yeah, that ^

signal tide
#

neat I'll have to play around with that

cloud crypt
#

and besides, you can freely subclass builtins if you know the consequences that you’ll have

raven ridge
#

super() calls the next class in the MRO. When you're instantiating a CounterList, that will be list, but when you're instantiating a subclass of CounterList, the next thing to be called after CounterList.__init__ isn't necessarily list.__init__

tawdry gulch
#

super() gets compiled differently tho right

#

Because how does it know the class it is currently in

raven ridge
#

it's handled specially when the file is parsed

tawdry gulch
#

right

#

what if you overwrite the variable super?

#

does it still get modified or does it the parser check for that

raven ridge
#

that's handled.

tawdry gulch
#

Right, makes sense

raven ridge
#

!e ```python
super = 42
class C:
def init(self):
super().init()
C()

fallen slateBOT
#

@raven ridge :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 5, in <module>
003 |   File "<string>", line 4, in __init__
004 | TypeError: 'int' object is not callable
tawdry gulch
#

Oh, awesome

#

Based python

raven ridge
#

Actually - this is kinda interesting. PEP 3135 says:

While super is not a reserved word, the parser recognizes the use of super in a method definition and only passes in the __class__ cell when this is found. Thus, calling a global alias of super without arguments will not necessarily work.

#

looks like if you redefine super and try to call it with no arguments from a class body, it is passed the class, actually, @tawdry gulch

#

!e ```py
super = print
class C:
def init(self):
super()
C()

fallen slateBOT
#

@raven ridge :warning: Your eval job has completed with return code 0.

[No output]
raven ridge
#

hm, and that behaved differently for me than it did for the bot!

In [7]: super = print
   ...: class C:
   ...:     def __init__(self):
   ...:         super()
   ...: C()
   ...: 

Out[7]: <__main__.C at 0x7dd9643d5e10>
feral cedar
#

maybe, the bot isn't a repl

gleaming rover
#

!e print()

fallen slateBOT
#

@gleaming rover :warning: Your eval job has completed with return code 0.

[No output]
gleaming rover
#

looks the same to me

#

looks like if you redefine super and try to call it with no arguments from a class body, it is passed the class, actually, @tawdry gulch
@raven ridge that's not passed to print

#

that's the displayed return value