L̶u̵m̶i̵n̷o̴u̶s̶m̶e̵n̵B̶l̵o̵g̵
503 subscribers
156 photos
32 videos
2 files
700 links
(ノ◕ヮ◕)ノ*:・゚✧ ✧゚・: *ヽ(◕ヮ◕ヽ)

helping robots conquer the earth and trying not to increase entropy using Python, Data Engineering and Machine Learning

http://luminousmen.com

License: CC BY-NC-ND 4.0
Download Telegram
Btw this also work for strings:

>>> a = 'the'
>>> b = 'the'
>>> a == b
True
>>> a is b
True

As the strings are immutable it makes sense for the interpreter to store the string literal only once and point all the variables to the same object. It is called string interning. And it's kind of internal optimization technique for working with valid identifiers.

In Python 3.6, any string with length ≤ 20 will get interned. But Python 3.7 uses the AST optimizer and (most) strings up to 4096 characters are interned.

>>> a = 'the thing'
>>> b = 'the thing'
>>> a == b
True
>>> a is b
False

Wtf you may be wonder. This string is just not a valid identifier that's all. But we can make interning explicit:

>>> import sys
>>> b = sys.intern('the thing')
>>> a = sys.intern('the thing')
>>> a == b
True
>>> a is b
True

Why?

🔸 Saving memory
🔸 Fast comparisons
🔸 Fast dictionary lookups

#python
There is a common misconception that GIL was invented to protect developers from problems with concurrent access to data. But this is not true.

GIL, of course, will prevent you from parallelizing an application using threads (but not processes). Simply put, GIL is a lock that must be taken before any access to Python (not that important if Python code is executing or calls using Python C API). Therefore, GIL will protect internal structures from non-consistent states, but you will have to use synchronization primitives like in any other language.

#python
The popular method to declare an abstract method in Python is to use NotImplentedError exception:

def func(self):
raise NotImplementedError


Though it's pretty popular and even has IDE support (Pycharm considers such a method to be abstract) this approach has a downside. You get the error only upon method call, not upon class instantiation.

Use abc module to avoid this problem:

from abc import ABCMeta, abstractmethod
class Service(metaclass=ABCMeta):
@abstractmethod
def func(self):
pass


#python
In Python if there are no references to the object, it is destroyed immediately, instead of waiting for garbage collection. GC is needed for complicated cases when we have cyclic references.

#python
The list may contain itself. Python detects this and does not loop in the output.

>>> a = []
>>> a.append(a)
>>> a
[[...]]


#python
Python doesn't have tail recursion optimization, not because Guido couldn't handle it, but because he doesn't want to overcomplicate things.

If you really want to, you can implement a Y-combinator with optimization and use it.

#python
Just like tail recursion in Python, Guido wanted to avoid getting lambda functions in the language. The lambda function is just sort of syntactic sugar. It creates an unnamed function - that's literally it. There is no magic to it.

Those two are equivalent:

foo = lambda x: x * 2

def foo(x):
return x * 2
foo.__qualname__ = '<lambda>'

We all know the lambda functions were introduced in the language, but there was a long fight behind it, which Guido did not win. Lambda still exists because it is extremely convenient and nothing else.

#python
A function can have two returns called. For example:

def foo():
try:
return 1
finally:
return 2


2 will be returned here.

#python
There are compilers for Python code. And not only JIT ones like Numba, but also ordinary ones. For example, Cython, Nuitka that compiles your Python code into true machine instructions rather than interpreted.

Why?

Basically for the sake of both performance gains and a more portable runtime. So basically it's for the guys who shouldn't use Python in the first place.

#python
Remember I told you about numbers from -5 to 255 interned. That is, the numbers are preliminary placed and cached in memory. So, there is more to it.

You can access this memory if you want and change value. Say, change literal 4 to value 5. I'll probably be damned by many people for this post, but here is a sample code:

>>> import ctypes
>>> ctypes.memmove(id(4) + 24, id(5) + 24, 8)
>>> print(2 * 2) # 5

Have fun debugging!

P.S. Try to replace 0 with 1

#python
The article on PythonSpeed compares three Python code analysis tools: Pylint, Flake8, and Ruff. Pylint is powerful but slow and complex, Flake8 is faster and simpler but less rigorous, and Ruff is a new tool that offers high speed with solid functionality, though it’s still maturing. The author suggests Ruff for new projects due to its balance of speed and features but acknowledges Pylint and Flake8 might be better suited for existing codebases.

🔗Link: https://pythonspeed.com/articles/pylint-flake8-ruff/

#article #python
💯4