Главная страница  Карта сайта  Печать  Написать письмо  RSS
Войти
Кнопка открытия главного меню
Персональный сайт
Стеллецкого Владимира
Обновлено: 31.03.2023 г.

Python

В 2009 году я решил изучить ещё какой-нибудь язык программирования. После анализа текущего выбора языков программирования я остановил свой выбор на Python или Ruby. После ещё некоторых колебаний склонился всё же к Python. Может быть когда-нибудь и до Ruby руки дойдут.

Если обнаружите ошибки или сможете предложить более "правильное" решение размещённых здесь задач, или же какую-то задачку для решения - пишите, буду очень признателен.

Ссылки (18.12.2019) #

« первая   ‹ предыдущая   1   2   3   следующая ›   последняя »

Новые фичи Python 3.8 и самое время перейти с Python 2 (25.01.2020) #

Наткнулся на статью с таким заголовком и решил ссылку на неё себе сохранить, тем более, что до сих пор использую Python 2.

Конечно, это не все нововведения третьей версии, так что Вас ждет ещё не мало открытий.

Табель сотрудников (28.10.2019) #

Выдалась возможность немного попрограммировать - сделать удобную форму для просмотра табеля одновременно всех сотрудников департамента. Хотелось упростить себе работу при табелировании и, главное, при корректировке табеля сотрудников работающих сменами, когда необходимо, чтобы обязательно кто-то был на работе.

В итоге остановился на web-страничке (HTML с CSS и JS) и скрипте на Python, который её формирует на основании информации из базы данных (тут, конечно же, не обошлось без SQL).

Табель сотрудников

На этой несложной задачке с удовольствием освежил в памяти знания по всем этим технологиям.

Также хотел бы отметить два удобных параметра запуска Python:

  • -i - после работы программы/скрипта войти в диалоговый режим. Это бывает удобно при отладке и поиске ошибок в скриптах (или при отказах).
  • -3 - выводит замечания к коду (вполне, возможно, работоспособному), который не сможет быть запущен в Python 3.x. Актуально, если приложение написано на второй версии, но Вы задумываетесь о переходе на третью версию.

Комментарии

Мой комментарий (29.06.2020)
Почти через год использования данного "решения" сделал ещё одну небольшую доработку - улучшил отображение этой странички на мобильных устройствах (постарался максимально сократить ширину таблицы).
Теперь, в случае открытия табеля с устройства с небольшим разрешением экрана, в таблице автоматически скрываются: год в дате, а также инициалы сотрудников (это позволило выиграть чуть больше четверти от начальной ширины таблицы и, соответственно, улучшить отображение на маленьких экранах).
Сделать это было не так сложно, так как изначально вёрстка страницы была несложная и приближенная к стандартам. С технической точки зрения на этапе формирования страницы выделил потенциально скрываемый текст (назначением отдельного класса), а потом добавил адаптивный стиль:
@media screen and (max-width: 1150px) {
    .io {
        display: none;
    }
    .year {
        display: none;
    }
}

Пенсионная реформа (06.02.2019) #

Была у меня одна простенькая задачка - определять по дате рождения пенсионер человек или нет.

До недавнего времени отлично работало следующее решение: из текущей даты вычитаем 60 и 55 лет и получаем минимальную дату рождения мужчины и женщины, для которых наступил пенсионный возраст. После этого сравниваем эту дату с датой рождения конкретного человека и определяем пенсионер он или нет. Ниже приведён код данного решения (только обсуждаемая часть):

import datetime

now_date = datetime.date.today() # Текущая дата (без времени)
cur_year = now_date.year # Год текущий
men_retirement_date = now_date.replace(year = cur_year - 60)
women_retirement_date = now_date.replace(year = cur_year - 55)

...

for people in list:
    if isMale:
        isPensioner = brs_date < men_retirement_date
    else:
        isPensioner = brs_date < women_retirement_date    

Решение было всем хорошее, кроме одного момента - при вычитании годов (для определения даты выхода на пенсию) не учитывалось, что в високосные годы в феврале на 1 день больше, поэтому при запуске 29 февраля программка вылетела с ошибкой преобразования даты.

Теперь же, после принятия новой пенсионной реформы, появился переходный период и пришлось писать отдельную функцию для того же функционала (посмотреть код).

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

PS Для прибавления 6 месяцев к указанной дате на StackOverflow предложили использовать отдельную библиотеку dateutil, но мне показалось, что в данном случае это было бы избыточно, да и лишнюю зависимость "тащить" не хотелось. Ниже предложенное там решение:

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

Напомню, что предварительно библиотеку надо установить: pip install python-dateutil

Python: коллекции (05.02.2017) #

Наткнулся на интересную для начинающих изучать Python серию статей посвященную коллекциям.

  • Часть 1: классификация, общие подходы и методы, конвертация
  • Часть 2: индексирование, срезы, сортировка
  • Часть 3: объединение коллекций, добавление и удаление элементов
  • Часть 4: Все о выражениях-генераторах, генераторах списков, множеств и словарей

Рекомендую к прочтению.

Произвольные коды (02.01.2016) #

На днях возникла необходимость получить 3,5 тысячи уникальных, но произвольных 12 значных цифровых кодов. Решений, очевидно, можно придумать массу, но скрипт на Python показался самым простым:

#-*- coding: utf-8 -*-
import random as r
codes = []
with file('oo.csv', 'w+') as f:
    while len(codes) < 3500:
        # cod = '11' + str(r.randint(int('1'*9), int('9'*9)))
        cod = '11' + ('0'*5 + str(r.randint(0, int('9'*5))))[-5:] 
        if cod not in codes:
            codes.append(cod)
            f.write(cod + '\n')

На всякий случай зарезервировал первые две позиции для "типа" - мало ли потом понадобится ещё что-то аналогичное, а также добавил (не в этом скрипте) в конец контрольный разряд (или число), который рассчитал по методу Луна (Lunh, см. Wikipedia).

UPD: Немного скорректировал скрипт: было решено сократить длину кода до 8 знаков, тогда для увеличения количества кодов решил произвольные составляющие искать с нуля, а не со всех единиц, как в первоначальном варианте, что потребовало выравнивания нулями слева. Первоначальный вариант тоже сохранил - закомментированная строка.

Тест на знание Python (23.05.2015) #

Коллега по работе прислал интересный тест на знание Python: https://alexbers.com/python_quiz/.
Тест в основном ориентирован на знание тонкостей и особенностей языка и классического интерпретатора.

Тест я, к сожалению, прошёл плохенько, так как мало практики и в нескольких местах поторопился и плохо подумал.
Интересующимся Python рекомендую попробовать пройти.

UPD: А вот коллега тест прошел очень хорошо - в 10 лучших! Говорит, что главное не торопиться и внимательно смотреть задание.

Python 2.7.x и 3.x (обзор различий) (08.08.2014) #

Коллега по работе прислал ссылку на интересное сравнение посвященное различиям второй и третьей версии Python.

Отдельно хотелось бы отметить два коварных момента, которые выявить будет довольно сложно, так как ошибки выполнения они не вызовут (просто программа будет работать не корректно):

Транспортный налог (18.10.2012) #

В связи с обсуждаемым изменением ставки транспортного налога в г. Москве, набросал крошечный скрипт для его расчета по текущим и обещанным (новым) ставкам:

#-*- coding: utf-8 -*-
tnc = list()
tnc.append((0, 0, 0))
tnc.append((70, 7, 12))
tnc.append((100, 20, 25))
tnc.append((125, 30, 35))
tnc.append((150, 38, 45))
tnc.append((175, 45, 50))
tnc.append((200, 60, 65))
tnc.append((225, 75, 75))
tnc.append((250, 150, 150))
tnc.append((410, 150, 300))

while True:
    title = u'Введите количество лошадиных сил (или ENTER для выхода): '
    print title
    title_e = 'Enter the amount of horsepower (or ENTER to exit): '
    s = raw_input(title_e)
    if s == '':
        break
    x = int(s)
    for c in tnc:
            if x > c[0]:
                    c1 = c
            else:
                    break
    print u'Транспортный налог для %s "лошадей" был %s р., станет %s р. (+%s р.) \n' % (x, x*c1[1], x*c1[2], x*(c1[2] - c1[1]))

Pythonic (15.03.2012) #

Начал читать книгу Дэвида М. Бизли - Python. Подробный справочник. Идёт не очень быстро, зато, кажется, стал проникаться философией питона - pythonic (подробнее здесь или здесь). Действительно хочется красивых и элегатных решений, тем более что для этого все предоставлено.

Как первый шаг удалось значительно упростить давнее (см. ниже), но периодически используемое решение, которое позволяет с легкостью реализовывать таблицы с историей изменений данных (изменённую версию опубликую чуть позже).

History к таблице (24.01.2010) #

Довольно часто стала возникать задача сделать историю изменений для какой-либо таблицы на MS SQL-сервере. У нас это реализуется путем создания дополнительной таблицы, содержащей все поля базовой + собственный идентификатор (H_ID) и тип операции вставка/обновление/удаление. Для записи в неё на базовой таблице создаются три триггера: after insert/update/delete, в которых осуществляется копирование данных. Делать каждый раз "руками" мне было лень, и я написал следующий скрипт:

# -*- coding: utf-8 -*-
import _mssql

import sys
class error:
    def write(self, text):
        open('error.log', 'a').write(text)
sys.stderr = error()

print u"2009 Stelletsky V. "
print u"Таблицы истории и триггеров"
print
#t = u"Название таблицы: "
tbname = raw_input("Table Name: ")
if tbname == "":
    sys.exit(1)

conn = _mssql.connect(server='servername', user='username', password='password', database='databasename')
# проверка существования таблиц
st = "SELECT * FROM INFORMATION_SCHEMA.TABLES "
st = st + "WHERE TABLE_NAME IN ('" + tbname + "', '" + tbname + "_H') ORDER BY TABLE_NAME"
conn.execute_query(st)
i = 0
for row in conn:
    if tbname <> row['TABLE_NAME'] and i==0:
        print u"Таблица %s не найдена!" % (row['TABLE_NAME']) 
        raw_input("Done")
        sys.exit(1)
    if tbname + "_H" == row['TABLE_NAME'] and i==1:
        print u"Таблица %s уже создана!" % (row['TABLE_NAME']) 
        raw_input("Done")
        sys.exit(1)
    i = i + 1
if i == 0:
    print u"Таблица '%s' не найдена!" % (tbname) 
    raw_input("Done")
    sys.exit(1)

print u"Создание таблицы %s" % (tbname + '_H')
st =      "SELECT * FROM INFORMATION_SCHEMA.[COLUMNS] c "
st = st + "WHERE c.TABLE_NAME = '" + tbname + "' "
conn.execute_query(st)
st = "CREATE TABLE [dbo].[" + tbname + "_H] ("
st = st + " [H_ID] int IDENTITY(1, 1) PRIMARY KEY NOT NULL, "
st = st + " [Operand] varchar(1) NOT NULL "
st_f = ""
for row in conn:
    st = st + ", "
    st_f = st_f + ", [" + row['COLUMN_NAME'] + "]"
    st = st + " [" + row['COLUMN_NAME'] + "] " + row['DATA_TYPE'] 
    if row['CHARACTER_MAXIMUM_LENGTH'] <> None:
        st = st + "(" + str(row['CHARACTER_MAXIMUM_LENGTH']) + ") "
    if row['COLLATION_NAME'] <> None:
        st = st + "COLLATE " + row['COLLATION_NAME']
    if row['IS_NULLABLE'] == "NO":
        st = st + " NOT"
    st = st + " NULL"
st = st + ")"        
conn.execute_non_query(st)
print u"Создание триггеров"
i = 0
while i < 3:
    if i == 0: 
        st_o = "I"
        st_op = "INSERT"
        st_from = "inserted"
    elif i == 1:
        st_o = "U"
        st_op = "UPDATE"
    elif i == 2:
        st_o = "D"
        st_op = "DELETE"
        st_from = "deleted"
    st =      "CREATE TRIGGER [dbo].[" + tbname + "_A" + st_o + "] ON [dbo].[" + tbname + "] "
    st = st + "WITH EXECUTE AS CALLER "
    st = st + "FOR " + st_op + " "
    st = st + "AS "
    st = st + "BEGIN "
    st = st + "  INSERT INTO dbo.[" + tbname + "_H] "
    st = st + "  (Operand" + st_f + ") "
    st = st + "  SELECT "
    st = st + "  '" + st_o + "'" + st_f + " "
    st = st + "  FROM " + st_from + " "
    st = st + "END "
    conn.execute_non_query(st)
    i = i + 1
    
raw_input("Done")

« первая   ‹ предыдущая   1   2   3   следующая ›   последняя »

  Вы 19 409 посетитель этой странички
с 05 марта 2009 года
© http://svv-home.ru
О сайте