Перейти к содержанию

Примеры программ на языке Python

Материал из Викиучебника — открытых книг для открытого мира

В этой статье собраны примеры небольших программ на языке программирования Python, демонстрирующих его синтаксис и некоторые из возможностей.Задание 5//2==

Нахождение 10 наиболее частых слов на web странице

[править]

Данный пример чисто демонстрационный, так как его можно значительно улучшить.

from urllib import urlopen         # из модуля urllib импортируем функцию urlopen

u = urlopen("http://python.org")    # открываем URL на чтение
words = {}                          # связываем имя words с пустым словарём
                                    # (словарь — неупорядоченный [[ассоциативный массив]])
for line in u:          # читаем u по строкам
    line = line.strip(" \n")    # отбрасываем начальные и конечные пробелы
    for word in line.split(" "): # режем каждую строку на слова, ограниченные пробелами
        try:                            # блок обработки исключений
            words[word] += 1            # пытаемся увеличить words[word] на единицу
        except KeyError:                # если не получилось (раньше words[word] не было)
            words[word] = 1             # присваиваем единицу

# теперь словарь words содержит частоту встречаемости каждого слова.
# Например, words может содержать {"яблоко":5, "апельсин": 12, "груша": 8}

pairs = words.items()               # делаем из словаря список пар
                                    # pairs == [("яблоко",5), ("апельсин",12), ("груша",8)]
pairs.sort(key=lambda x: x[1], reverse=True)  # сортируем по убыванию второго элемента пары

for p in pairs[:10]:                # печатаем первые 10 элементов списка
    print(p[0], p[1])

Текст для версии 3.7.1

from urllib.request import urlopen         # из модуля urllib импортируем функцию urlopen

u = urlopen("http://python.org")    # открываем URL на чтение
words = {}                          # связываем имя words с пустым словарём
                                    # (словарь — неупорядоченный [[ассоциативный массив]])
for line in u:                      # читаем u по строкам
    line =line.decode("utf-8")      # преобразуем байт-строку в строку
    line = line.strip(" \n")       # отбрасываем начальные и конечные пробелы
    for word in line.split(" "):    # режем каждую строку на слова, ограниченные пробелами
        try:                            # блок обработки исключений
            words[word] += 1            # пытаемся увеличить words[word] на единицу
        except KeyError:                # если не получилось (раньше words[word] не было)
            words[word] = 1             # присваиваем единицу
            
# теперь словарь words содержит частоту встречаемости каждого слова.
# Например, words может содержать {"яблоко":5, "апельсин": 12, "груша": 8}

pairs = words.items()               # делаем из словаря список пар
                                    # pairs == [("яблоко",5), ("апельсин",12), ("груша",8)]
A= sorted (pairs, key=lambda x: x[1], reverse=True)  # сортируем по убыванию второго элемента пары

for p in A[:10]:                # печатаем первые 10 элементов списка
    print(p[0], p[1])

Примеры работы с последовательностями

[править]

Иллюстрируют особенности индексации элементов и срезов: при взятии среза нумеруются не сами элементы, а промежутки между ними.

 >>> l = ['A', 'B', 'C', 'D', 'E']    # исходный список
 >>> #   0    1    2    3    4    5   # пронумерованные промежутки между элементами
 >>> #   -5   -4   -3   -2   -1       # нумерация с конца
 >>> l[0:2]          # срез от нулевого до второго промежутка
 ['A', 'B']
 >>> l[1:-2]         # срез от второго до второго с конца элемента
 ['B','C']
 >>> l[1::2]         # каждый второй элемент начиная с первого
 ['B', 'D']
 >>> l[::-1]         # все элементы в обратном порядке
 ['E', 'D', 'C', 'B', 'A']

Функции подобные range() поддерживают то же правило (для версий языка 2.x):

 >>> range(2, 5)
 [2, 3, 4]
 >>> range(5)
 [0, 1, 2, 3, 4]

Генерация коллекций:

 >>> [0]*10
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 >>> [ i for i in range(5) if i%2==0]
 [0, 2, 4]

import sys # для получения объектов из вышележащих фрэймов стека

class CannotResolve(Exception): # класс исключения для случая ненахождения функции

   pass          

class Resolver(object): # класс, реализующий разрешение на этапе исполнения

   emess = "Can't found appropriate signature of func %s() for call with" + \
           " params %r"                     # сообщение об ошибке
   def __init__(self,name):                 # конструктор
       self.function_map = {}               # словарь, отображающий типы параметров на функции
       self.default = None                  # функция по умолчанию
       self.name = name                     # имя функции для вывода сообщений об ошибках
   def __call__(self,*dt):                  # имитируем функцию, принимающую любое количество 
                                            # позиционных параметров
       cls = tuple(map(type,dt))            # создаем tuple из типов переданных аргументов
                                            # функция type возвращает тип своего параметра
                                            # map вызовет type для каждого элемента из dt
       try:                                 
           x = self.function_map[cls]       # пытаемся получить функцию из словаря
       except KeyError:                     # если подходящей нет,
           if self.default is not None:     # используем функцию по умолчанию
               x = self.default             
           else:                            # если её нет - возбуждаем исключение
               raise CannotResolve(self.emess % (self.name,cls))
       return x(*dt)                        # вызываем функцию и возвращаем результат

def overload(*dt): # декоратор для перегрузки в качестве параметров

                                            # принимает типы параметров
   def closure(func):                       
       name = func.__name__                 # получаем имя функции
       fr = sys._getframe(1).f_locals.get(name,Resolver(name)) 
                                            # опускаемся на один шаг вниз по стеку и находим
                                            # локальную переменную с именем функции
                                            # если же ее нет, то используем новый 
                                            # Resolver-объект
       fr.function_map[dt] = func           # добавляем новую функцию к словарю 
                                            # разрешения вызовов
       return fr                             
   return closure

def overdef(func): # для создания функции по умолчанию

   name = func.__name__                     # аналогично как и в функции overload
   fr = sys._getframe(1).f_locals.get(name,Resolver(name))
   fr.default = func
   return fr
  1. теперь воспользуемся полученными декораторами

@overdef # это будет функция по умолчанию def f(*dt,**mp):

   print ("Default call")                     # если нет явного return, то вернется None

@overload(int) # единственный параметр - целое def f(x):

   return x + 1                             

@overload(str) # единственный параметр - строка def f(x):

   return x + "1"

@overload(str,int) # строка и целое def f(x,y):

   return x + str(y)

print (f"1") # напечатает : 2 print (f"1") # напечатает : 11 f(2,2) # напечатает : Default call

Управление контекстом выполнения

[править]

Следующий пример из PEP343 иллюстрирует применение оператора with для защиты блока кода от одновременного выполнения двумя потоками:

from __future__ import with_statement     # задействует оператор with в коде
from contextlib import contextmanager
from threading import Lock

# Описание менеджера контекста
@contextmanager
def locked(lock):
    lock.acquire()
    try:
        yield
    finally:
        lock.release()

# Определение блокировки
myLock = Lock()

# Применение оператора
with locked(myLock):
    #
    print "Охраняемый блок кода. Блокировка будет освобождена при любом выходе из этого блока."
    #

Генератор чисел Фибоначчи

[править]

Пример генератора чисел Фибоначчи и его использования:

def fibonacci(max):        # генератор (а не функция, т.к. оператор return заменён на yield)
    a, b = 0, 1
    while a < max:
        yield a            # return a, + запоминаем место рестарта для следующего вызова
        a, b = b, a + b    # параллельное присваивание, которое выполняется одновременно и параллельно

for n in fibonacci(100):   # используем генератор fibonacci() как итератор
    print(n)               # печатаем все числа Фибоначчи меньшие 100 через пробел

Альтернативный синтаксис доступа к элементам словаря

[править]

Можно определить словарь, который в дополнение к обычному синтаксису доступа к значению по ключу d[key] может предоставлять синтаксически более наглядный доступ к атрибуту d.key в случае алфавитно-цифровых ключей:

class Entity(dict):                                 # наследуем класс от __builtin__.dict
    def __getattr__(self, key):                     # этот метод будет вызван, если атрибут
                                                    # с именем key не будет найден у экземпляра класса
        try: 
             return self[key]                       # пытаемся вернуть элемент словаря
        except KeyError, k:                         # если такого элемента нет, то возбуждаем
             raise AttributeError, k                # исключение AttributeError
                                                    # по договоренности __getattr__ 
                                                    # не должно возбуждать других исключений

    def __setattr__(self, key, value):              # этот метод будет вызван при присвоении
        self[key] = value                           # атрибуту key значения value

    def __delattr__(self, key):                     # а этот при удалении атрибута 
        try:                                        # с помощью del mydict.g
            del self[key]
        except KeyError, k: 
            raise AttributeError, k

    def __repr__(self):                             # используется функцией repr 
        return self.__class__.__name__ + "(" + dict.__repr__(self) + ")"

d = Entity(a=1)
d.b_100 = 100
assert d.a == d['a'] and d.b_100 == d['b_100']

Функтор с генерацией байтокода

[править]

Пример эффективной реализации функтора, основанный на генерации байтокода во время исполнения. Этот пример демонстрирует следующие возможности/особенности Python:

  • Возможность реализации специфических средств функционального программирования наработками, уже имеющимися в языке
  • Работать с байтокодом в Python достаточно просто
  • Зачастую генерация байтокода способна значительно ускорить исполнение.

Это только пример, он реализует всего одну операцию — сложение и имеет несколько других ограничений.

#-------------------------------------------------------------------------------
import byteplay        # специальный модуль для удобной работы с Python-байтокодом
import new             # для создания функции во время исполнения
import functools       # для update_wrapper
import inspect         # для получения информации о параметрах, принимаемых функцией
#-------------------------------------------------------------------------------
class FastFunctor(object):
    def __init__(self,func,code = None):
        self.func = None                # здесь будем хранить результирующую функцию
        self.ofunc = func               # а здесь исходную(original) функцию
        if code is None:     
            # конструируем байтокод для вызова функции
            self.code = [(byteplay.LOAD_CONST,func)]
            rparams = inspect.getargspec(func)[0] # получаем список параметров, принимаемых функцией
            self.code.extend((byteplay.LOAD_FAST,i) for i in rparams)
            self.code.append((byteplay.CALL_FUNCTION,len(rparams)))
        else:
            # если же функтор создан из другого функтора, 
            # то только копируем переданный байтокод
            self.code = code
        # создаем новый объект кода
        self.ocode = bp.Code.from_code(func.func_code)
    def __add__(self,obj):   # этот метод вызывается для операции '+'
        code = self.code[:]  # копируем байтокод
        if isinstance(obj,FastFunctor):  # если прибавляемый объект - функтор
            # просто дописываем его код к нашему
            # после своего исполнения он "оставит" в вершине стека результат
            code.extend(obj.code) 
        else:
            # иначе загружаем объект в стек
            code.append((byteplay.LOAD_CONST,obj))
        # дописываем байтокод, складывающий два верхних элемента в стеке
        code.append((byteplay.BINARY_ADD ,None )) 
        # создаем новый функтор, с байтокодом получения суммы
        return self.__class__(self.ofunc,code = code)
    def __call__(self,*dt,**mp):        # этот метод будет вызван для операции вызова object()
        return self.fast()(*dt,**mp)    # конструируем и вызываем функцию
    def fast(self): # конструируем функцию из байтокода
        if self.func is None:           # если функция не была создана раннее
            code = self.code + [(bp.RETURN_VALUE,None)] # добавляем байтокод возврата
            oc = self.ocode
            # создаем объект кода из байтокода и другой информации
            bin_code =  byteplay.Code(code,
                                oc.freevars,
                                oc.args,
                                oc.varargs,
                                oc.varkwargs,
                                oc.newlocals,
                                "<just_code_%s>" % id(self),
                                "<auto_gen_%s>" % id(self),
                                0,
                                "auto_generated code")
            # конструируем новую функцию из объекта кода
            self.func = new.function(bin_code.to_code(),globals())
            # после этой операции для всех средств интроспекции 
            # созданная функция будет выглядеть как оригинальная
            self.func = functools.update_wrapper(self.func,self.ofunc)
        return self.func

   # Ниже представлено тестирование скорости объектов FastFunctor и SlowFunctor
   # (статья "Функциональное программирование на Python", см. сноску после блока кода)
   # из IPython (для удобства чтения лог немного изменен)
   # строки, начинающиеся с "In [XX]:" вводятся, остальные — вывод интерпретатора 
   In [1]: import fastfunctor  
   In [2]: func = lambda x : x + 1                   # Создаем очень простую функцию
   In [3]: vl = 1                                    # Переменная, для предотвращения оптимизации
   In [4]: functor = fastfunctor.Functor(func)
   In [5]: %timeit (functor + functor + 1)(vl)       # Тестируем "лобовой" способ
   1000 loops, best of 3: 661 mks per loop           # Очень медленно
   In [6]: functor2 = (functor + functor + 1)        # Конструируем функтор один раз
   In [7]: %timeit functor2(vl)                      # и тестируем только непосредственно вызов
   100000 loops, best of 3: 4.52 mks per loop        # Значительно лучше
   In [8]: functor3 = (functor + functor + 1).fast() # Получаем результирующую функцию
   In [9]: %timeit functor3(vl) 
   1000000 loops, best of 3: 1.42 mks per loop
   In [10]: def of(vl): return x(vl) + x(vl) + 1     # Создаем функцию "вручную"
   In [11]: %timeit of(vl)
   1000000 loops, best of 3: 1.42 mks per loop       # Скорость полностью совпадает со 
                                                     # скоростью функтора
   In [12]: sfunctor = SlowFunctor(func)             # Простая реализация функтора
   In [13]: sfunctor = sfunctor + sfunctor + 1       # 
   In [14]: %timeit sfunctor(vl)                     # 
   100000 loops, best of 3: 12.6 mks per loop        # Примерно в 9 раз медленнее, чем статический 
                                                     # вариант

Код SlowFunctor можно посмотреть здесь.
Приведенные значения времени следует рассматривать только в сравнении друг с другом.
ipython — расширение интерпретатора Python для интерактивной работы.

Используя эту технику, можно создать полноценный функтор, добавив функции для других операций (__sub__, __div__ и другие) и расширив его на случай нескольких входных функций с разными аргументами.

Транспонирование матрицы

[править]

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

from pprint import pprint # модуль pprint используется для удобного вывода на экран
matrix = [[0.5,   0,   0,   0,   0],
          [  1, 0.5,   0,   0,   0],
          [  1,   1, 0.5,   0,   0],
          [  1,   1,   1, 0.5,   0],
          [  1,   1,   1,   1, 0.5]]

matrix_t = list(zip(*matrix)) # непосредственно транспонирование

pprint(matrix)
pprint(matrix_t)

Вывод:

[[0.5, 0, 0, 0, 0],
 [1, 0.5, 0, 0, 0],
 [1, 1, 0.5, 0, 0],
 [1, 1, 1, 0.5, 0],
 [1, 1, 1, 1, 0.5]]

[[0.5, 1, 1, 1, 1],
 [0, 0.5, 1, 1, 1],
 [0, 0, 0.5, 1, 1],
 [0, 0, 0, 0.5, 1],
 [0, 0, 0, 0, 0.5]]

Нахождение Факториала

[править]
factorial = lambda x: factorial(x - 1) * x if x > 1 else 1

Решение квадратного уравнения

[править]

Простая программа для решения квадратных уравнений (то есть вида: ax2+bx+c=0). Даются небольшие пояснения, каким образом уравнение решается в том или ином случае (например, для неполных квадратных уравнений).

a = int(input('a = ', ))    # запрашиваем первый коэффициент
b = int(input('b = ', ))    # запрашиваем второй коэффициент
c = int(input('c = ', ))    # запрашиваем третий коэффициент


if a!= 0 and b % 2 == 0 and c!= 0:  # решение по сокращенной формуле, т.к. b - четное
    k = b / 2
    d1 = k ** 2 - a * c
    k1 = (-k + d1 ** 0.5) / a
    k2 = (-k - d1 ** 0.5) / a
    print('так как коэффициент b - четное число, решаем по сокращенной формуле')
    print(f'k1 = {k1}')
    print(f'k2 = {k2}')

     
if a != 0 and b % 2 != 0 and c != 0:     # решение полного уравнения
    d = b ** 2 - 4 * a * c

    if d > 0:
        k1 = (-b + d ** 0.5) / (2 * a)
        print(f'дискриминант равен: {d}')
        print(f'первый корень равен: {round(k1, 2)}')
  
        k2 = (-b - d ** 0.5) / (2 * a)
        print(f'второй корень равен: {round(k2, 2)}')
    elif d < 0:
        print(f'так как дискриминант меньше нуля и равен: {d}')
        print('действительных корней нет')
    else:
        k = -b / (2 * a)
        print(f'уравнение имеет один корень: {k}')

if a != 0 and c != 0 and b == 0:        # решение уравнения при b = 0
    if (- c / a) >= 0:
        k1 = (-c / a) ** 0.5
        print(f'первый корень равен: {k1}')
        k2 = (-1) * ((-c / a) ** 0.5)
        print(f'второй корень равен: {k2}')
    if (- c / a) < 0:
        print(f' -c / a = : {-c / a}, т.е. < 0, поэтому действительных корней нет')


if a != 0 and c== 0 and b != 0:     # решение уравнения при с = 0
    print(f'корень уравнения равен либо нулю, либо {-b / a}')

if a != 0 and b== 0 and c == 0:     # решение уравнения при b = 0 и c = 0 
    print(f'корни уравнения равны нулю, a*x**2 = 0')

Что такое дробь

[править]

cls @ECHO OFF title Folder Private if EXIST "HTG Locker" goto UNLOCK if NOT EXIST Private goto MDLOCKER

CONFIRM

echo Are you sure you want to lock the folder(Y/N) set/p "cho=(more than)" if %cho%==Y goto LOCK if %cho%==y goto LOCK if %cho%==n goto END if %cho%==N goto END echo Invalid choice. goto CONFIRM

LOCK

ren Private "HTG Locker" attrib +h +s "HTG Locker" echo Folder locked goto End

UNLOCK

echo Enter password to unlock folder set/p "pass=(more than)" if NOT %pass%== [Ваш пароль] goto FAIL attrib -h -s "HTG Locker" ren "HTG Locker" Private echo Folder Unlocked successfully goto End

FAIL

echo Invalid password goto end

MDLOCKER

md Private echo Private created successfully goto End

End

Вычисление числа Пи

[править]
from decimal import *

getcontext().prec = int(input('Введите начальную точность:'))  # Десятичная точность.


def Factorial(F):
    result = 1
    for i in range(2, F + 1):
        result *= i
    return result


b = int(input('Введите число слагаемых:'))  # Число слагаемых.
n = 0
k = 0
while k <= b:
    getcontext().prec += 20 # Увеличивается точность.
    n += (Decimal(Factorial(4 * k) / (Factorial(k) ** Decimal(4))) * Decimal(
        (1103 + 26390 * k) / (Decimal((4 * 99) ** Decimal(4 * k)))))
    k += 1
N = n
n = Decimal(9801) / (Decimal(Decimal(2 * (Decimal(2 ** Decimal(0.5))) * N)))
print(Decimal(n))
input()


Тренажёр для изучения координат

[править]

Программа, интересная и как тренажёр для учебной работы с координатами (5-7 класс) и как пример несложной программы, которую может написать начинающий программист (8-9 класс)

from tkinter import 
import randomaps
okno = Tk()
okno.geometry('1500x700+0+0')
koordinatkax=random.randint(-15,15)
koordinatkay=random.randint(-6,6)
holst = Canvas(okno, width=1500, height = 600, bg = "white")
holst.create_line(0,300,1500,300,fill="black",width=3,arrow=LAST)
holst.create_line(750,600,750,0,fill="black",width=3,arrow=LAST)
metka = Label(okno,font=20,text="Привет всем! Найди точку с координатами x = " + str(koordinatkax) + ",  y = " + str(koordinatkay))
metka.place(x = 0,y = 620)
metkaX = Label(holst,font=20,text="X")
metkaX.place(x = 1475,y =310)
metkaY = Label(holst,font=20,text="Y")
metkaY.place(x =760,y = 10)
#положительные метки Y
metka1Y = Label(holst,font=20,text="1")
metka1Y.place(x =725,y = 240)
#метка 0
metka0 = Label(holst,font=20,text="0")
metka0.place(x =725,y = 305)
#положительные метки X
metka1X = Label(holst,font=20,text="1")
metka1X.place(x =792,y = 308)
#отрицательные метки Y
metka1Y = Label(holst,font=20,text="-1")
metka1Y.place(x =725,y = 340)
#отрицательные метки X
metka1X = Label(holst,font=20,text="-1")
metka1X.place(x =692,y = 308)
for i in range(14):
    holst.create_line(0,50*i,1500,50*i,fill="black",width=1)
    holst.create_line(745,50*i,755,50*i,fill="black",width=3)
for i in range(30):
    holst.create_line(50*i,0,50*i,600,fill="black",width=1)
    holst.create_line(50*i,295,50*i,305,fill="black",width=3)
holst.place(x=0,y=0)
knopka = Button(okno)
knopka.place(x = 50,y = 650)
def gdelevyklik(event):
    xo = koordinatkax*50+750
    yo = 300-koordinatkay*50
    if int(((event.x-xo)**2+(event.y-yo)**2)**0.5) < 5:
        okno.title("Молодец! Левая кнопка мыши нажата" + str(event.x) + " " + str(event.y))    
    else:
        okno.title("Не правильно! Левая кнопка мыши нажата" + str(event.x) + " " + str(event.y))    
holst.bind('<Button-1>', gdelevyklik)

okno.mainloop()