Лекция 6-й недели. Введение в Python

5 (100%) 3 vote[s]

Python — это еще один язык программирования, но он интерпретируется (запускается сверху вниз интерпретатором, как JavaScript) и имеет более высокий уровень, чем С (включает более мощные функции и библиотеки).

Например, мы можем реализовать всю resize, написанную нами ранее на языке C, всего за несколько строк с помощью Python:

import sys
from PIL import Image

if len(sys.argv) != 4:
    sys.exit("Usage: python resize.py n infile outfile")

n = int(sys.argv[1])
infile = sys.argv[2]
outfile = sys.argv[3]

inimage = Image.open(infile)
width, height = inimage.size
outimage = inimage.resize((width * n, height * n))

outimage.save(outfile)
  • Во-первых, мы импортируем import (как includesys библиотеку (для аргументов командной строки) и Image библиотеку.
  • Мы проверяем , что есть правильное число аргументов командной строки с len(sys.argv), а затем создаем несколько переменных ninfile и outfile, без необходимости указывать их тип.
  • Затем мы используем библиотеку изображений, чтобы открыть входное изображение, получить его ширину и высоту, изменить его размер с помощью функции  resize и, наконец, сохранить его в выходной файл.

Давайте посмотрим на новый синтаксис. В Python мы можем создавать переменные просто counter = 0. Чтобы увеличить переменную, мы можем использовать counter = counter + 1 или counter += 1.

Условия выглядят так:

if x < y:
    something
elif:
    something
else:
    something
  • В отличие от C и JavaScript (при этом для блоков кода используются фигурные скобки { } ), точный отступ каждой строки определяет уровень вложенности в Python.

Булевы выражения тоже немного отличаются:

 
while True:     
something 

Циклы могут быть созданы с помощью другой функции range, которая в приведенном ниже примере возвращает диапазон чисел от 0 до 50, но не включая:

 
for i in range(50):     
something 

В Python мы начнем с рассмотрения лишь нескольких типов данных:

  • boolTrueилиFalse;
  • float, вещественные числа;
  • intцелые числа;
  • str, строки;
  • dictсловарь пар ключ-значение, которые действуют как хеш-таблицы;
  • list, как массивы, но может автоматически изменять размер
  • range диапазон значений;
  • set, коллекция уникальных вещей;
  • tuple группа из двух или более вещей.

В Python мы тоже можем включить библиотеку CS50, наш синтаксис будет таким:

from cs50 import get_float, get_int, get_string

Обратите внимание, что мы указываем функции, которые мы хотим использовать.

В Python мы можем запустить нашу программу, не компилируя её  (python hello.py).

  • python — это имя программы, которую мы на самом деле запускаем из командной строки, и это интерпретатор, который может читать наш исходный код (написанный на языке Python) и запускать его по одной строке за раз. (Технически, существует компилятор, который превращает наш исходный код в нечто, называемое байт-кодом, которое фактически выполняет интерпретатор, но это абстракция для нас.)

Типы данных в Python

Наша первая hello.pyпрограмма простая:

         print("hello, world")
  • Обратите внимание, что нам не нужна функция  main или что-либо, которую нам нужно было импортировать для функции printфункции. Функция print в Python также добавляет новую строку для нас автоматически.
  • Теперь мы можем запустить его с python hello.py.

Мы можем получить строки от пользователя:

from cs50 import get_string

s = get_string("Name: ")
print("hello,", s)
  • Мы создаем переменную с именем s без указания типа, и мы можем передать несколько переменных в функцию print, которая выведет их для нас на одной строке, автоматически разделенных пробелом.
  • Чтобы избежать лишних пробелов, мы можем поместить переменные внутри строки, подобно тому, как они включены в C: print(f"hello, {s}"). Здесь мы говорим, что строка hello, {s}является отформатированной строкой с символом f перед строкой, и поэтому переменная s будет подставлена ​​в строку. И нам не нужно беспокоиться о типе переменной; мы можем просто включить их в строки.

Также мы можем добавить немного математики:

from cs50 import get_int

x = get_int("x: ")

y = get_int("y: ")

print(f"x + y = {x + y}")
print(f"x - y = {x - y}")
print(f"x * y = {x * y}")
print(f"x / y = {x / y}")
print(f"x mod y = {x % y}")
  • Обратите внимание, что выражения like {x + y} будет оцениваться или вычисляться до того, как оно будет подставлено в строку для печати.
  • Запустив эту программу, мы увидим, что все работает так, как мы могли ожидать, даже разделив два целых числа, чтобы получить значение с плавающей запятой. (Чтобы сохранить прежнее поведение всегда возвращать усеченное целое с делением, есть //оператор.)

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

from cs50 import get_float

x = get_float("x: ")

y = get_float("y: ")

z = x / y

print(f"x / y = {z}")
  • Когда мы запускаем эту программу, мы видим следующее:
$ python floats.py
x: 1
y: 10
x / y = 0.1
  • Мы можем напечатать больше десятичных знаков с синтаксисом, например print(f"x / y = {z:.50f}"):
x / y = 0.10000000000000000555111512312578270211815834045410

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

Мы можем проверить, имеет ли Python целочисленное переполнение:

from time import sleep

i = 1
while True:
    print(i)
    i *= 2
    sleep(1)

Мы используем функцию sleep, чтобы приостановить нашу программу на одну секунду, но удваиваем iснова и снова. И получается, что целые числа в Python могут быть настолько большими, насколько позволяет память, поэтому мы не будем испытывать переполнение в течение гораздо более длительного времени.

Программирование на Python

Давайте внимательнее посмотрим на условия:

from cs50 import get_int

# Get x from user
x = get_int("x: ")

# Get y from user
y = get_int("y: ")

# Compare x and y
if x < y:
    print("x is less than y")
elif x > y:
    print("x is greater than y")
else:
    print("x is equal to y")
  • Обратите внимание, что мы используем последовательный отступ, но нам не нужны скобки или скобки для наших условий.
  • Комментарии тоже начинаются с одного #символа.

Мы можем сравнивать строки так, как мы могли бы ожидать:

from cs50 import get_char

# Prompt user for answer
c = get_string("Answer: ")

# Check answer
if c == "Y" or c == "y":
    print("yes")
elif c == "N" or c == "n":
    print("no")
  • Строки можно сравнивать напрямую, а логические выражения могут включать слова and и or.

Мы можем написать функции в Python следующим образом:

def main():
    for i in range(3):
        cough()


def cough():
    """Cough once"""
    print("cough")


if __name__ == "__main__":
    main()
  • Мы используем  ключевое слово def для определения функции cough, указывающей, что она не принимает никаких параметров или входных данных, используя just (), и вызываем ее из нашей функции main. Обратите внимание, что весь код для каждой функции имеет дополнительный отступ, а не заключен в фигурные скобки.
  • Затем, ниже, мы используем специальную строку if __name__ == "__main__":для вызова функции main при запуске нашей программы. Таким образом, интерпретатор узнает о
    функции cough к тому моменту, когда main действительно вызывается. Мы могли бы также вызвать cough напрямую, вместо main, хотя это было бы нетрадиционно в Python. (Вместо этого мы хотим попытаться быть «питонами» или следовать стилям и шаблонам, поощряемым языком и его сообществом.)

Мы также можем добавить параметры и циклы в функцию  cough:

def main():
    cough(3)


def cough(n):
    for i in range(n):
        print("cough")


if __name__ == "__main__":
    main()
  • n переменная, которую можно передать в cough и которую мы также можно передать в range. И обратите внимание, что мы не указываем типы в Python, поэтому n может быть любым типом данных (ему даже может быть присвоено значение другого типа).

Мы можем определить функцию, чтобы получить положительное целое число:

from cs50 import get_int


def main():
    i = get_positive_int("Positive integer: ")
    print(i)


def get_positive_int(prompt):
    while True:
        n = get_int(prompt)
        if n > 0:
            break
    return n


if __name__ == "__main__":
    main()
  • Поскольку в Python нет цикла do-while, как в C, у нас есть whileцикл, который будет продолжаться бесконечно, но мы используем break для завершения цикла if n > 0. Тогда наша функция будет просто return n.
  • Обратите внимание, что переменные в Python по умолчанию имеют область действия функции, что означает, что n могут быть инициализированы в цикле, но все же будут доступны позже в функции.

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

from cs50 import get_string

s = get_string()
for c in s:
    print(c.upper(), end="")
print()
  • Обратите внимание, что мы можем легко перебирать символы в строке чем-то вроде for c in s, и мы печатаем версию каждого символа в верхнем регистре с помощью c.upper(). Строки в Python — это объекты, такие как структура данных с сохраняемым значением, а также встроенные функции .upper(), которые мы можем вызвать.
  • Наконец, мы передаем в функцию  print  еще один аргумент, чтобы end=""каждый раз печатал новую строку. Python имеет именованные аргументы, где мы можем называть аргументы, которые мы можем передавать, в дополнение к позиционным аргументам, в зависимости от их положения в списке. С именованными аргументами мы можем передавать аргументы в разных порядках и полностью опускать необязательные аргументы. Обратите внимание, что этот пример помечен end, указывая строку, которой мы хотим завершить каждую напечатанную строку. Передавая пустую строку"", ничего не будет напечатано после каждого символа. Раньше, когда мы вызывали print без end аргумента, в качестве функции \nпо умолчанию использовалась функция end, которая позволяет автоматически получать новые строки.

Мы можем получить длину строки с помощью len()функции.

from cs50 import get_string

s = get_string("Name: ")
print(len(s))

Мы будем использовать 3-ю версию Python, которую мир начинает использовать все больше и больше, поэтому при поиске документации мы хотим быть уверены, что она подходит для правильной версии.

Мы можем взять аргументы командной строки с:

from sys import argv

if len(argv) == 2:
    print(f"hello, {argv[1]}")
else:
    print("hello, world")
  • Мы проверяем количество аргументов, посмотрев на длину argv, список аргументов, и, если есть 2, мы печатаем второй. Как и в C, первый аргумент командной строки — это имя программы, которую мы написали, а не слово python, которое технически является именем программы, которую мы запускаем в командной строке.
  • Мы можем напечатать каждый аргумент в списке:
from sys import argv

for s in argv:
    print(s)
    • Это будет перебирать каждый элемент в списке argv, что позволяет нам использовать его как s.

И мы можем перебирать каждый символ каждого аргумента:

from sys import argv

for s in argv:
    for c in s:
        print(c)
    print()

Мы можем поменять две переменные в Python, просто изменив их порядок:

x = 1
y = 2

print(f"x is {x}, y is {y}")
x, y = y, x
print(f"x is {x}, y is {y}")
  • Здесь мы используем , x, y = y, xчтобы установить , xчтобы yв то же время , как установка yдля x.

Мы можем создать список и добавить к нему:

from cs50 import get_int

numbers = []

# Prompt for numbers (until EOF)
while True:

    # Prompt for number
    number = get_int("number: ")

    # Check for EOF
    if not number:
        break

    # Check whether number is already in list
    if number not in numbers:

        # Add number to list
        numbers.append(number)

# Print numbers
print()
for number in numbers:
    print(number)
  • Здесь мы создаем пустой список с именем numberswith numbers = [] и получаем number от пользователя. Если этого numberеще нет в нашем списке, мы добавляем его в наш список. Мы можем использовать, not in чтобы проверить, есть ли значение (нет) в списке, и append добавить значение в конец списка.

Мы можем создавать собственные структуры данных, объекты:

from cs50 import get_string

# Space for students
students = []

# Prompt for students' names and dorms
for i in range(3):
    name = get_string("name: ")
    dorm = get_string("dorm: ")
    students.append({"name": name, "dorm": dorm})

# Print students' names and dorms
for student in students:
    print(f"{student['name']} is in {student['dorm']}.")
  • Мы создаем список с именем students, и после того, как мы получим некоторую информацию от пользователя, мы добавляем в этот список словарь пар ключ-значение {"name": name, "dorm": dorm}. Здесь "name"и "dorm"находятся ключи, и мы хотим, чтобы их значения были переменными, которые мы собрали в качестве входных данных. Затем мы можем позже получить доступ к значениям каждого объекта с помощью student['name'] или student['dorm'] и распечатать их. В Python мы можем индексировать в словари словами или строками, а не просто числовыми индексами в списках.

Давайте напечатаем четыре знака вопроса, по одному за раз:

for i in range(4):
    print("?", end="")
print()

Мы также можем напечатать вертикальную полосу хеш-меток:

for i in range(3):
    print("#")

И мы можем напечатать квадрат с вложенным циклом:

for i in range(3):
    for j in range(3):
        print("#", end="")
    print()

Теперь мы можем вернуться resize.py, и это может иметь больше смысла для нас сейчас:

from PIL import Image
from sys import argv

if len(sys.argv) != 4:
    sys.exit("Usage: python resize.py n infile outfile")

n = int(sys.argv[1])
infile = sys.argv[2]
outfile = sys.argv[3]

inimage = Image.open(infile)
width, height = inimage.size
outimage = inimage.resize((width * n, height * n))

outimage.save(outfile)
  • Мы импортируем библиотеку изображений из чего-то, называемого PIL, бесплатной библиотеки с открытым исходным кодом, которую мы можем загрузить и установить (которая по умолчанию не поставляется с Python).
  • Затем мы импортируем argv из библиотеки системы, и мы проверяем наши аргументы, сохраняя их в качестве ninfileи outfile, преобразование входной строки для n в  int.
  • Читая документацию по Python и библиотеке изображений, мы можем открывать файлы в виде изображения, получать его size и вызывать для него resize функцию, чтобы получить другое изображение, которое мы затем можем передать save в другой файл.

Давайте посмотрим на другой пример, проверку орфографии в Python:

# Words in dictionary
words = set()

def check(word):
    """Return true if word is in dictionary else false"""
    return word.lower() in words

def load(dictionary):
    """Load dictionary into memory, returning true if successful else false"""
    file = open(dictionary, "r")
    for line in file:
        words.add(line.rstrip("\n"))
    file.close()
    return True

def size():
    """Returns number of words in dictionary if loaded else 0 if not yet loaded"""
    return len(words)

def unload():
    """Unloads dictionary from memory, returning true if successful else false"""
    return True
  • Функции для dictionary.pyдовольно просты, так как все, что нам нужно — это set(), коллекция, в которую мы можем загружать уникальные значения. В load мы открываем dictionaryфайл и добавляем каждую строку в файле как слово (без символа новой строки).
  • Для checkмы можем просто вернуть будь то word  в words, а для size мы можем просто вернем длину words. Наконец, нам не нужно ничего делать unload, поскольку Python управляет памятью за нас.

Используя сначала C, мы получили понимание алгоритма и реализуем его в абстракции, которые предоставляет нам язык более высокого уровня, такой как Python. Действительно, если мы запустим некоторые тесты на производительность, реализация speller в Python может быть в 1,5 раза медленнее, и поэтому в зависимости от приложения, это может быть или не быть достаточно важным, чтобы оправдать человеческое время, которое может потребоваться для написания программы в язык более низкого уровня, такой как C, который может работать намного быстрее или требовать меньше памяти.

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

Читайте больше по теме:

Подписаться
Уведомление о
guest
0 комментариев
Inline Feedbacks
View all comments
Просмотры: 461

Популярные записи