48 вещей о Python, которые я до недавнего времени не знал (сборник)

48 вещей о Python, которые я до недавнего времени не знал (сборник)

1) Мы можем динамически устанавливать переменные, используя globals()

a = 4 b = 5

^ это то же самое, что:

globals()['a'] = 4 globals()['b'] = 5

globals()— это словарь, содержащий все глобальные переменные, и мы можем устанавливать переменные, добавляя пары ключ-значение в него (не делайте этого в производственном коде).

2) re.sub может принимать функции

# replacing vowels with - import re x = re.sub('[aeiou]', '-', 'apple') print(x) # -ppl-
# replacing vowels with UPPERCASE vowels import re x = re.sub('[aeiou]', lambda x:x.group().upper(), 'apple') print(x) # ApplE

^ мы можем передать функцию вместо строки в re.sub

3) Мы можем внедрить CSS в jupyter

import pandas as pd from IPython.display import HTML # this function adds some CSS to our dataframe def upsidedown(df): html = '''<style> .dataframe {transform: rotate(180deg)} </style>''' + df.to_html() display(HTML(html))
df = pd.DataFrame([ ['apple', 4],['orange', 5],['pear', 6], ['pineapple', 7], ['banana', 8], ], columns=['fruit', 'price']) upsidedown(df)
48 вещей о Python, которые я до недавнего времени не знал (сборник)

В функцию upsidedown вводится CSS, из-за которого наш фрейм данных отображается вверх ногами.

4) Разница между __getattr__ и __getattribute__

class Dog: def __init__(self, name, age): self.name = name self.age = age def __getattr__(self, attr): return f'__getattr__ called: {attr} does not exist' def __getattribute__(self, attr): return f'__getattribute__ called {attr}={super().__getattribute__(attr)}' dog = Dog('rocky', 4) print(dog.name) # __getattribute__ called name=rocky print(dog.breed) # __getattr__ called: breed does not exist
  • __getattribute__вызывается, когда мы пытаемся получить существующий атрибут.
  • __getattr__вызывается, когда мы пытаемся получить несуществующий атрибут.

Имхо, это немного странно, но это то, что есть.

5) Отладчик Python

В Python есть встроенный отладчик pdb, который позволяет нам проверять каждую переменную на каждом этапе. Нам нужны 2 файла .py:

# testfile.py (contains the function we want to debug) def testfunction(): x = 'apple' breakpoint() y = 'orange'
# debug.py (we run this file) import pdb import testfile pdb.run('testfile.testfunction()')

На каждом этапе мы можем использовать команды PDB, например continue или exist, или вводить имена переменных, например x или y.

6) Учитывание регистра в Python (Python 3.10+)

Это доступно только в Python 3.10 и выше, и мы можем думать об этом как об элегантном блоке if-elif-else.

fruit = 'apple' match fruit: case 'apple': print('apple pie') case 'orange': print('orange squash') case 'pear': print('pear cake') # apple pie

7) Мы можем рисовать на Python (программно), используя turtle

import turtle screen = turtle.getscreen() x = turtle.Turtle() for i in range(1000): x.forward(200) x.right(115)

turtle— это встроенный модуль, который позволяет нам рисовать с помощью Python. Выполнение приведённого выше кода рисует цветок:

48 вещей о Python, которые я до недавнего времени не знал (сборник)

8) Мы можем скрыть пользовательский ввод в терминале

from getpass import getpass print('Please enter your password below') password = getpass() # whatever user types is hidden print(password)

Что произойдет, когда мы запустим это и наберём 'apple':

Please enter your password below Password: apple

Когда мы набираем apple, всё, что мы набираем, скрыто, как обычный пароль.

9) Переменная __debug__

# python hello.py print(__debug__) # __debug__ is usually True
# python -O hello.py print(__debug__) # False # __debug__ becomes False when we use the -O flag

Когда __debug__ равен False, операторы assert игнорируются.

10) Мы можем открыть наш браузер с помощью Python

import webbrowser webbrowser.open_new("https://medium.com")

^ если мы запустим приведённый выше код, medium.com откроется в вашем браузере.

Примечание — это встроенная программа, и нам не нужно её устанавливать.

11) Дроби в Python

from fractions import Fraction x = Fraction(1/2) print(x/3) # 1/6

мы можем представлять дроби, используя объекты Fraction вместо чисел с плавающей запятой (встроено, не нужно устанавливать)

12) Python имеет встроенную медианную функцию

from statistics import median print(median([3,1,5,2,4])) # 3

^ statistics— это встроенный модуль, который нам не нужно устанавливать.

13) Мы можем заставить вещи запускаться ПОСЛЕ оператора return в функции

def test(): print('apple') return 1 print('orange') # this won't ever be printed

^ в типичных функциях НИЧЕГО не происходит после выполнения инструкции return. Строка print('orange')никогда не будет выполнена.

def test(): try: print('apple') return 1 finally: print('orange') # this will run even after a return statement

Однако, если мы используем блок try-finally, блок finally выполняется ВСЕГДА. Таким образом, строка print('orange')появляется ПОСЛЕ оператора return.

14) Мы можем использовать .update() для объединения 2 словарей/наборов

dict1 = {'apple':4, 'orange':5} dict2 = {'pear': 6} dict1.update(dict2) # dict1 = {'apple':4, 'orange':5, 'pear':6}
set1 = {'apple', 'orange'} set2 = {'pear'} set1.update(set2) #set1 = {'apple', 'orange', 'pear'}

15) int() равно 0, а float() равно 0,0

print(int()) # 0 print(float()) # 0.0

16) Мы можем использовать __code__ для получения информации о функции

def test(a, b, c): apple = 100
print(test.__code__.co_argcount) # 3 print(test.__code__.co_varnames) # ('a', 'b', 'c', 'apple') print(test.__code__.co_consts) # (None, 100, 200) print(test.__code__.co_filename) # /your/filepath/file.py

__code__позволяет нам получить определённые метаданные о функциях.

17) PYTHONPATH появляется в sys.path

# how to set the PYTHONPATH env variable (use cmd/terminal) set PYTHONPATH=yourfolder # Windows export PYTHONPATH=yourfolder # MacOS / Linux etc
# assume we're running this from /your/filepath import sys print(sys.path) # ['/your/filepath', '/your/filepath/yourfolder', ... ]

После установки PYTHONPATH он появляется в sys.path. Это означает, что мы можем запускать файлы /your/filepath/yourfolder без необходимости записывать их на компакт-диск.

18) Расширение .py не имеет большого значения

# hello.txt print('hello from hello.txt')
# test.chicken print('hello from test.chicken')

Расширение .py не имеет значения, если файл содержит действительный код Python. Но, пожалуйста, не делайте этого в производственном коде.

19) Отображение прокси (неизменяемые словари)

Прокси-серверы — это словари, которые нельзя изменить после того, как мы их создадим. Мы используем их, если не хотим, чтобы наши пользователи изменяли их значения.

# defining a mapping proxy from types import MappingProxyType mp = MappingProxyType({'apple':4, 'orange':5})
# what happens when we try to reassign a key from types import MappingProxyType mp = MappingProxyType({'apple':4, 'orange':5}) mp['apple'] = 10 # Traceback (most recent call last): # File "some/path/a.py", line 4, in <module> # mp['apple'] = 10 # ~~^^^^^^^^^ # TypeError: 'mappingproxy' object does not support item assignment

20) __dict__ отличается для классов и объектов

class Dog : def __init__ ( self, name, age ): self.name = name self.age = age rocky = Dog( 'rocky' , 5 )
# an object's __dict__ is a normal dict print(type(rocky.__dict__)) # <class 'dict'> print(rocky.__dict__) # {'name': 'rocky', 'age': 5}
# a class' __dict__ is a mapping proxy (immutable dict) print(type(Dog.__dict__)) # <class 'mappingproxy'> print(Dog.__dict__) # {'__module__': '__main__', ...... }

Таким образом, мы не можем редактировать атрибуты класса и т. д. с помощью __dict__.

21) any() и all()

any ([ True , False , False ]) # True any ([ False , False , False ]) # False

^ any() возвращает True, если хотя бы один элемент имеет значение True.

all ([ True , False , False ]) # False all ([ True , True , True ]) # True

^ all()возвращает True, если КАЖДЫЙ элемент имеет значение True.

22) divmod()

quotient, remainder = divmod(27, 10) # quotient = 2, remainder = 7

^ встроенная функция divmod() делает // и в то же время %.

27//10 возвращает 2, а 27%10 возвращает 7, поэтому (2,7)возвращается с divmod(27, 10).

23) Мы можем легко проверять переменные, используя f-строки

name = 'rocky' age = 5 gender = 'm' print(f'{name=} {age=} {gender=}') # name='rocky' age=5 gender='m'

^ нам просто нужно вставить {varname=} в f-строку.

24) Мы можем автоматически конвертировать числа с плавающей запятой

print(float.as_integer_ratio(0.5)) # (1, 2) print(float.as_integer_ratio(0.25)) # (1, 4) print(float.as_integer_ratio(1.5)) # (3, 2)

Встроенная функция float.as_integer_ratio() позволяет нам преобразовать число с плавающей запятой в дробь (представленную кортежем).

# but sometimes it behaves funky print(float.as_integer_ratio(0.1)) # (3602879701896397, 36028797018963968)

25) globals() и local()

# globals() returns a dict containing all global variables x = 1 print(globals()) # {'__name__': '__main__', '__doc__': None, ..., 'x': 1}
# locals() returns a dict containing all local variables def test(): x,y = 1,2 print(locals()) test() # {'x': 1, 'y': 2}

26) __import__()

# normal way of importing stuff import numpy as np import pandas as pd
# using __import__ (doing the exact same thing as above) np = __import__('numpy') pd = __import__('pandas')

27) Положительная/отрицательная бесконечность в Python

a = float('inf') # positive infinity b = float('-inf') # negative infinity

Положительная бесконечность больше всех остальных чисел, а отрицательная бесконечность меньше всех остальных чисел (обычно).

28) Мы можем использовать pprint для красивой печати

from pprint import pprint # which stands for 'pretty print' d = {"A":{"apple":1, "orange":2, "pear":3}, "B":{"apple":4, "orange":5, "pear":6}, "C":{"apple":7, "orange":8, "pear":9}} pprint(d)
48 вещей о Python, которые я до недавнего времени не знал (сборник)

29) Мы можем печатать цветной вывод в Python

Сначала нам нужен следующий код pip install colorama (в cmd/терминал).

from colorama import Fore print (Fore.RED + "hello world" ) print (Fore.BLUE + "hello world" ) print (Fore.GREEN + "hello world" )
48 вещей о Python, которые я до недавнего времени не знал (сборник)

30) Более быстрый способ набрать словарь (иногда)

d1 = {'apple':'pie', 'orange':'juice', 'pear':'cake'} # normal way
d2 = dict(apple='pie', orange='juice', pear='cake') # faster way

31) Мы можем распечатать материал в Python

CURSOR_UP = '\033[1A' CLEAR = '\x1b[2K' print('apple') print('orange') print('pear') print((CURSOR_UP + CLEAR)*2, end='') # this unprints 2 lines print('pineapple')
48 вещей о Python, которые я до недавнего времени не знал (сборник)
  • CURSOR_UP перемещает наш курсор вверх на 1 строку
  • CLEAR очищает всю текущую строку
  • print(CURSOR_UP + CLEAR)вместе печатают 1 строку

32) Частные переменные в объектах не являются частными

class Dog: def __init__(self, name): self.__name = name # self.__name is supposed to be private @property def name(self): return self.__name rocky = Dog('rocky') print(rocky.__dict__) # {'_Dog__name': 'rocky'}

Мы можем получить доступ к __name с помощью __dict__или даже rocky._Dog__name.

33) Мы можем создавать классы, используя type()

# creating a class normally class Dog: def __init__(self, name, age): self.name = name self.age = age def bark(self): print(f'Dog({self.name}, {self.age})')
def __init__(self, name, age): self.name = name self.age = age def bark(self): print(f'Dog({self.name}, {self.age})') # creating a class using type() Dog = type('Dog', (), {'__init__':__init__, 'bark':bark})

Когда мы передаём 3 аргумента в type(), мы можем создать класс:

classname = type(name, bases, dict)
  • classname— переменная, представляющая имя класса, например - Dog
  • name— строка, представляющая имя класса, например.'Dog'
  • bases— кортеж, содержащий родительские классы класса
  • dict— словарь, содержащий атрибуты и методы класса

34) Мы можем использовать китайские иероглифы в качестве переменных

我 = 4 你 = 5 print(我 + 你) # 9

Пожалуйста, не используйте это в производственном коде

35) Символ возврата \b

print('abc\bd') # abd

Печать символа возврата \b удаляет один напечатанный символ

36) Символ колокольчика \a

print('\a')

Печать \a должна издавать колокольный звон. Попробуйте это в CMD/терминале.

37) Классы могут быть декораторами

class add (): def __init__ ( self, char ): self.char = char def __call__ ( self, function ): def inner ( *args ): return function(*args) + self.char return inner @add( "! " ) def welcome ( name ): return "hello" + name print (greet ( "tom" )) # hello tom!

Это возможно благодаря магическому методу __call__, который определяет, что происходит, когда мы вызываем объект add.

38) Функции могут иметь переменные и методы

def test(): test.var = 200 # setting a variable test.func = lambda:300 # setting a method return 100 print(test()) # 100 print(test.var) # 200 print(test.func()) # 300

Крутая вещь, но, пожалуйста, не используйте это в производственном коде

39) Простой способ выравнивания строк

# using f-strings print(f'>{"hello":<10}<') # >hello < print(f'>{"hello":>10}<') # > hello< print(f'>{"hello":^10}<') # > hello <
# using ljust/rjust/center print('>' + 'hello'.ljust(10) + '<') # >hello < print('>' + 'hello'.rjust(10) + '<') # > hello< print('>' + 'hello'.center(10) + '<') # > hello <

40) Что происходит, когда мы добавляем список к самому себе?

lis = ['apple', 'orange'] lis.append(lis) print(lis) # ['apple', 'orange', [...]]

...называется многоточием и отображается функцией print при наличии циклических ссылок. ...также может использоваться в качестве кода-заполнителя.

41) Мы можем запускать строки как код, используя eval()

print ( eval ( '4+5' )) # 9 print ( eval ( '7-3' )) #4 eval ( 'print(12345)' ) #12345

42) round() принимает отрицательные десятичные разряды

# rounding off to nearest 10, 100, 1000 etc print(round(12345, -1)) # 12340 print(round(12345, -2)) # 12300 print(round(12345, -3)) # 12000 # rounding off to 2 decimal places print(round(3.14159, 2)) # 3.14

43) Оператор моржа := (Python 3.8+)

# a simple if block n = 5 if n > 3: print('n is more than 3') # doing the exact same thing using the walrus operator := if (n := 5) > 3: print('n is more than 3')

В (n := 5):

1. Переменной n присвоено значение 5

2. 5 также возвращается (поэтому его можно использовать для сравнения с 3)

Мы можем использовать оператор walrus, чтобы сохранить одну строку кода.

44) Мы можем собрать много объектов в один и тот же файл

Встроенный модуль pickle позволяет нам сохранять структуры данных или объекты Python в двоичные файлы. Мы можем сохранить несколько объектов в файл.

# saving a, b & c into test.pckl a = [1,2,3] b = [4,5,6] c = [7,8,9] import pickle with open('test.pckl', 'wb') as f: pickle.dump(a, f) # saving a into test.pckl (1st object) pickle.dump(b, f) # saving b into test.pckl (2nd object) pickle.dump(c, f) # saving c into test.pckl (3rd object)
# reading test.pckl to get 3 objects import pickle with open('test.pckl', 'rb') as f: a = pickle.load(f) # a = [1,2,3] b = pickle.load(f) # b = [4,5,6] c = pickle.load(f) # c = [7,8,9]

45) Запуск нашего скрипта Python с флагом -O позволяет нам игнорировать некоторые ошибки

м# run.py assert 1==2 print('hi')

Если мы запускаем python run.py, assert 1==2 вызывает AssertionError.

Если мы запускаем python -O run.py, assert 1==2 игнорируется из-за -O.

46) dict.fromkeys()

Это позволяет нам создать словарь из списка.

fruits = ['apple', 'orange' ,'pear'] # creating dict from fruits d = dict.fromkeys(fruits) # {'apple':None, 'orange':None, 'pear':None}

^ все значения None соответствуют значениям None по умолчанию.

fruits = ['apple', 'orange' ,'pear'] d = dict.fromkeys(fruits, 5) # {'apple':5, 'orange':5, 'pear':5}

^ мы можем сами установить значение по умолчанию, передав другой аргумент в dict.fromkeys

47) Frozensets (Неизменные наборы)

Frozensets — это наборы, которые нельзя изменить после создания.

# basic frozenset creation fs = frozenset({1,2,3})
# attempting to add stuff results in an error fs.add(4) # ERROR

Преимущества замороженных наборов:

  • Проверка существования чего-либо внутри замороженного набора по-прежнему занимает время O(1)
  • Мы можем добавить замороженный набор в другой набор (мы не можем сделать это с наборами).
  • Мы можем использовать замороженный набор в качестве ключа словаря (мы не можем сделать это с наборами).

48) Мы можем заставить классы принимать только определённые переменные, используя __slots__

# Dog class can only have 'name' & 'age' attributes class Dog: __slots__ = ['name', 'age']
dog = Dog() dog.name = 'apple' # ok dog.age = 1 # ok dog.gender = 'm' # ERROR cus 'gender' is not in __slots__

Заключение

Надеюсь, сегодня вы узнали хоть что-то новое о Python!

2
Начать дискуссию