Spec-Zone.ru › Python 3.12

Вопросы и ответы по библиотекам и расширениям

  • Общие вопросы по библиотекам

    • Как найти модуль или приложение для выполнения задачи X?
    • Где находится исходный файл math.py (socket.py, regex.py и т.д.)?
    • Как сделать скрипт Python исполняемым на Unix?
    • Есть ли пакет curses/termcap для Python?
    • Есть ли эквивалент функции C onexit() в Python?
    • Почему мои обработчики сигналов не работают?
  • Общие задачи

    • Как протестировать программу или компонент Python?
    • Как создать документацию из строк документации?
    • Как получить один нажатие клавиши за раз?
  • Потоки

    • Как программировать с использованием потоков?
    • Ни один из моих потоков не запускается: почему?
    • Как распределить работу между несколькими потоками-работниками?
    • Какие типы глобальных изменений значений безопасны для потоков?
    • Нельзя ли избавиться от глобальной блокировки интерпретатора?
  • Ввод и вывод

    • Как удалить файл? (И другие вопросы о файлах…)
    • Как скопировать файл?
    • Как читать (или записывать) двоичные данные?
    • Я не могу использовать os.read() на конвейере, созданном с помощью os.popen(); почему?
    • Как получить доступ к последовательному (RS232) порту?
    • Почему закрытие sys.stdout (stdin, stderr) не приводит к реальному закрытию?
  • Программирование сети/Интернета

    • Какие инструменты WWW есть для Python?
    • Как имитировать отправку CGI-формы (METHOD=POST)?
    • Какой модуль следует использовать для генерации HTML?
    • Как отправить почту из скрипта Python?
    • Как избежать блокировки в методе connect() сокета?
  • Базы данных

    • Есть ли интерфейсы к пакетам баз данных в Python?
    • Как реализовать персистентные объекты в Python?
  • Математика и численные методы

    • Как сгенерировать случайные числа в Python?

Общие вопросы по библиотекам

Как найти модуль или приложение для выполнения задачи X?

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

Для сторонних пакетов выполните поиск в Python Package Index или попробуйте Google или другой поисковик в интернете. Поиск по ключевым словам “Python” плюс один-два ключевых слова по интересующей теме обычно даёт полезную информацию.

Где находится исходный файл math.py (socket.py, regex.py и т.д.)?

Если вы не можете найти исходный файл модуля, он может быть встроенным или динамически загружаемым модулем, реализованным на C, C++ или другом языке компиляции. В этом случае у вас может не быть исходного файла или он может находиться где-то в каталоге C (не в пути Python).

В Python есть (по крайней мере) три типа модулей:

  1. модули, написанные на Python (.py);
  2. модули, написанные на C и загружаемые динамически (.dll, .pyd, .so, .sl и т.д.);
  3. модули, написанные на C и связанные с интерпретатором; чтобы получить список этих модулей, введите:

    import sys
    print(sys.builtin_module_names)
    

Как сделать скрипт Python исполняемым на Unix?

Для этого нужно сделать две вещи: разрешение файла скрипта должно быть исполняемым, а первая строка должна начинаться с #!, за которым следует путь к интерпретатору Python.

Первое делается выполнением chmod +x scriptfile или, возможно, chmod 755 scriptfile.

Второе можно сделать несколькими способами. Самый простой способ — написать

#!/usr/local/bin/python

в качестве первой строки файла, используя путь к интерпретатору Python, установленному на вашей платформе.

Если вы хотите, чтобы скрипт не зависел от места расположения интерпретатора Python, вы можете использовать программу env. Практически все варианты Unix поддерживают следующее, предполагая, что интерпретатор Python находится в каталоге в пользовательской PATH:

#!/usr/bin/env python

Не делайте этого для CGI-скриптов. Переменная PATH для CGI-скриптов часто очень минимальна, поэтому вам нужно использовать фактический абсолютный путь к интерпретатору.

Иногда окружение пользователя настолько перегружено, что программа /usr/bin/env даёт сбой; или программы env вообще нет. В этом случае вы можете попробовать следующую хитрость (придумал Алекс Резинский):

#! /bin/sh
""":"
exec python $0 ${1+"$@"}
"""

Незначительный недостаток заключается в том, что это определяет строку документации скрипта __doc__. Однако вы можете исправить это, добавив

__doc__ = """...Whatever..."""

Есть ли пакет curses/termcap для Python?

Для вариантов Unix: стандартное распределение исходного кода Python содержит модуль curses в подкаталоге Modules, хотя он не компилируется по умолчанию. (Обратите внимание, что это не доступно в дистрибутиве для Windows — модуля curses для Windows нет.)

Модуль curses поддерживает базовые функции curses, а также многие дополнительные функции из ncurses и SYSV curses, такие как цвет, поддержка альтернатного набора символов, панели и поддержка мыши. Это означает, что модуль несовместим с операционными системами, в которых есть только BSD curses, но, похоже, в настоящее время нет поддерживаемых ОС, которые попадают в эту категорию.

Есть ли эквивалент функции C onexit() в Python?

Модуль atexit предоставляет функцию регистрации, аналогичную функции C onexit().

Почему мои обработчики сигналов не работают?

Наиболее распространённая проблема заключается в том, что обработчик сигнала объявлен с неправильным списком аргументов. Он вызывается как

handler(signum, frame)

поэтому он должен быть объявлен с двумя параметрами:

def handler(signum, frame):
    ...

Общие задачи

Как протестировать программу или компонент Python?

Python поставляется с двумя фреймворками для тестирования. Модуль doctest находит примеры в docstring модуля и выполняет их, сравнивая вывод с ожидаемым выводом, указанным в docstring.

Модуль unittest представляет собой более продвинутый фреймворк для тестирования, основанный на фреймворках Java и Smalltalk.

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

«Глобальная основная логика» вашей программы может быть такой простой, как

if __name__ == "__main__":
    main_logic()

в нижней части основного модуля вашей программы.

После того, как ваша программа организована как управляемый набор функций и поведений классов, вы должны написать тестовые функции, которые проверят эти поведения. С каждым модулем может быть связан набор тестов, который автоматизирует последовательность тестов. Это может показаться большой работой, но поскольку Python настолько лаконичен и гибок, это удивительно легко. Вы можете сделать процесс кодирования более приятным и увлекательным, написав свои тестовые функции параллельно с «производственным кодом», так как это облегчит обнаружение ошибок и даже архитектурных недостатков на ранней стадии.

«Вспомогательные модули», которые не предназначены для того, чтобы быть основным модулем программы, могут включать самотестирование модуля.

if __name__ == "__main__":
    self_test()

Даже программы, взаимодействующие со сложными внешними интерфейсами, могут быть протестированы, когда внешние интерфейсы недоступны, с помощью «фиктивных» интерфейсов, реализованных на Python.

Как создать документацию из doc-строк?

Модуль pydoc может генерировать HTML из doc-строк в вашем исходном коде Python. Альтернативой для создания документации API исключительно из doc-строк является epydoc. Sphinx также может включать содержимое doc-строк.

Как получить одиночный нажатый ключ?

Для вариантов Unix существует несколько решений. Это просто сделать с помощью curses, но curses — это довольно большой модуль для изучения.

Потоки

Как программировать с использованием потоков?

Не забудьте использовать модуль threading, а не модуль _thread. Модуль threading создает удобные абстракции поверх низкоуровневых примитивов, предоставляемых модулем _thread.

Ни один из моих потоков, похоже, не работает: почему?

Как только основной поток завершается, все потоки убиваются. Ваш основной поток работает слишком быстро, не давая потокам времени на выполнение работы.

Простым решением является добавление задержки в конце программы, достаточной для завершения всех потоков:

import threading, time

def thread_task(name, n):
    for i in range(n):
        print(name, i)

for i in range(10):
    T = threading.Thread(target=thread_task, args=(str(i), i))
    T.start()

time.sleep(10)  # <---------------------------!

Но теперь (на многих платформах) потоки не выполняются параллельно, а, похоже, выполняются последовательно, по одному за раз! Причина в том, что планировщик потоков ОС не запускает новый поток до тех пор, пока предыдущий поток не заблокируется.

Простым решением является добавление небольшой задержки в начале функции run:

def thread_task(name, n):
    time.sleep(0.001)  # <--------------------!
    for i in range(n):
        print(name, i)

for i in range(10):
    T = threading.Thread(target=thread_task, args=(str(i), i))
    T.start()

time.sleep(10)

Вместо того, чтобы пытаться угадать хорошее значение задержки для time.sleep(), лучше использовать какой-либо механизм семафора. Одна из идей — использовать модуль queue для создания объекта очереди, позволить каждому потоку добавить маркер в очередь при завершении и позволить главному потоку прочитать столько маркеров из очереди, сколько потоков.

Как распределить работу между несколькими рабочими потоками?

Самый простой способ — использовать модуль concurrent.futures, особенно класс ThreadPoolExecutor.

Или, если вы хотите точный контроль над алгоритмом диспетчеризации, вы можете написать свою логику вручную. Используйте модуль queue для создания очереди, содержащей список задач. Класс Queue поддерживает список объектов и имеет метод .put(obj) для добавления элементов в очередь и метод .get() для их возврата. Класс позаботится о блокировках, необходимых для обеспечения того, чтобы каждая задача обрабатывалась ровно один раз.

Вот тривиальный пример:

import threading, queue, time

# The worker thread gets jobs off the queue.  When the queue is empty, it
# assumes there will be no more work and exits.
# (Realistically workers will run until terminated.)
def worker():
    print('Running worker')
    time.sleep(0.1)
    while True:
        try:
            arg = q.get(block=False)
        except queue.Empty:
            print('Worker', threading.current_thread(), end=' ')
            print('queue empty')
            break
        else:
            print('Worker', threading.current_thread(), end=' ')
            print('running with argument', arg)
            time.sleep(0.5)

# Create queue
q = queue.Queue()

# Start a pool of 5 workers
for i in range(5):
    t = threading.Thread(target=worker, name='worker %i' % (i+1))
    t.start()

# Begin adding work to the queue
for i in range(50):
    q.put(i)

# Give threads time to run
print('Main thread sleeping')
time.sleep(5)

При выполнении этого кода будет выведен следующий результат:

Running worker
Running worker
Running worker
Running worker
Running worker
Main thread sleeping
Worker <Thread(worker 1, started 130283832797456)> running with argument 0
Worker <Thread(worker 2, started 130283824404752)> running with argument 1
Worker <Thread(worker 3, started 130283816012048)> running with argument 2
Worker <Thread(worker 4, started 130283807619344)> running with argument 3
Worker <Thread(worker 5, started 130283799226640)> running with argument 4
Worker <Thread(worker 1, started 130283832797456)> running with argument 5
...

Для получения более подробной информации см. документацию модуля; класс Queue предоставляет функциональный интерфейс.

Какие виды глобальных изменений значений безопасны для потоков?

Внутренне используется глобальная блокировка интерпретатора (GIL), чтобы гарантировать, что только один поток работает в виртуальной машине Python за раз. В целом, Python предлагает переключаться между потоками только между инструкциями байткода; частоту переключения можно задать с помощью sys.setswitchinterval(). Каждая инструкция байткода, а следовательно, и весь код реализации на C, достижимый из каждой инструкции, является атомарным с точки зрения программы Python.

Теоретически, для точного учета требуется точное понимание реализации байткода PVM. На практике это означает, что операции со общими переменными встроенных типов данных (целые числа, списки, словари и т. д.), которые «выглядят атомарными», действительно являются таковыми.

Например, следующие операции являются атомарными (L, L1, L2 — списки, D, D1, D2 — словари, x, y — объекты, i, j — целые числа):

L.append(x)
L1.extend(L2)
x = L[i]
x = L.pop()
L1[i:j] = L2
L.sort()
x = y
x.field = y
D[x] = y
D1.update(D2)
D.keys()

Эти не являются:

i = i+1
L.append(L[-1])
L[i] = L[j]
D[x] = D[x] + 1

Операции, заменяющие другие объекты, могут вызывать метод __del__() этих других объектов, когда их счетчик ссылок достигает нуля, и это может повлиять на ситуацию. Это особенно актуально для массовых обновлений словарей и списков. В случае сомнений используйте мьютекс!

Разве мы не можем избавиться от глобальной блокировки интерпретатора?

Глобальная блокировка интерпретатора (GIL) часто рассматривается как препятствие для развертывания Python на высокопроизводительных многопроцессорных серверных машинах, потому что многопоточная программа Python фактически использует только один процессор из-за того, что (почти) весь код Python может выполняться только при удержании GIL.

В те времена, когда Python был 1.5, Greg Stein фактически реализовал полный набор исправлений (патчи «бесплатной многопоточности»), которые убрали GIL и заменили его на мелкозернистые блокировки. Adam Olsen недавно провел аналогичный эксперимент в своем проекте python-safethread. К сожалению, оба эксперимента показали резкое падение производительности однопоточных программ (по крайней мере, на 30% медленнее) из-за необходимого количества мелкозернистых блокировок для компенсации удаления GIL.

Это не означает, что вы не можете эффективно использовать Python на многопроцессорных машинах! Вам просто нужно проявить изобретательность, разделив работу между несколькими процессами, а не несколькими потоками. Класс ProcessPoolExecutor в новом модуле concurrent.futures предоставляет простой способ сделать это; модуль multiprocessing предоставляет низкоуровневый API, если вы хотите получить больший контроль над диспетчеризацией задач.

Целесообразное использование расширений на C также поможет; если вы используете расширение C для выполнения длительной задачи, расширение может освободить GIL, пока поток выполнения находится в коде C, и позволить другим потокам выполнить некоторую работу. Некоторые стандартные библиотечные модули, такие как zlib и hashlib, уже делают это.

Было предложено, что GIL должен быть блокировкой на уровне состояния интерпретатора, а не глобальной; тогда интерпретаторы не смогут совместно использовать объекты. К сожалению, этого, скорее всего, не произойдет. Это потребует огромного объема работы, потому что во многих реализациях объектов сейчас используется глобальное состояние. Например, небольшие целые числа и короткие строки кэшируются; эти кэши должны быть перемещены в состояние интерпретатора. Другие типы объектов имеют свои собственные свободные списки; эти свободные списки должны быть перемещены в состояние интерпретатора. И так далее.

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

И, наконец, после того, как у вас есть несколько интерпретаторов, не разделяющих состояние, что вы получили в сравнении с запуском каждого интерпретатора в отдельном процессе?

Вход и вывод

Как удалить файл? (И другие вопросы о файлах…)

Используйте os.remove(filename) или os.unlink(filename); для документации см. модуль os. Эти две функции идентичны; unlink() просто имя системного вызова Unix для этой функции.

Для удаления каталога используйте os.rmdir(); для создания используйте os.mkdir(). os.makedirs(path) создаст все промежуточные каталоги в path, если они не существуют. os.removedirs(path) удалит промежуточные каталоги, пока они непустые; если вы хотите удалить всю древовидную структуру каталога и её содержимое, используйте shutil.rmtree().

Для переименования файла используйте os.rename(old_path, new_path).

Для обрезки файла откройте его с помощью f = open(filename, "rb+"), и используйте f.truncate(offset); смещение по умолчанию равно текущей позиции поиска. Также есть os.ftruncate(fd, offset) для файлов, открытых с помощью os.open(), где fd - дескриптор файла (маленькое целое число).

Модуль shutil также содержит ряд функций для работы с файлами, включая copyfile(), copytree() и rmtree().

Как скопировать файл?

Модуль shutil содержит функцию copyfile(). Обратите внимание, что на томах Windows NTFS он не копирует альтернативные потоки данных ни ресурсные вилки на macOS HFS+ томах, хотя оба сейчас редко используются. Также он не копирует права доступа к файлам и метаданные, хотя использование shutil.copy2() вместо этого сохранит большинство (хотя и не все) из них.

Как читать (или писать) двоичные данные?

Для чтения или записи сложных двоичных форматов данных лучше всего использовать модуль struct. Он позволяет преобразовывать строку, содержащую двоичные данные (обычно числа), в объекты Python и наоборот.

Например, следующий код считывает два 2-байтовых целых числа и одно 4-байтовое целое число в формате big-endian из файла:

import struct

with open(filename, "rb") as f:
    s = f.read(8)
    x, y, z = struct.unpack(">hhl", s)

‘>’ в строке формата принудительно задаёт big-endian данные; буква ‘h’ считывает одно «короткие целое число» (2 байта), а ‘l’ считывает одно «длинное целое число» (4 байта) из строки.

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

Примечание

Для чтения и записи двоичных данных необходимо открыть файл в двоичном режиме (здесь передавая "rb" в open()). Если вы используете "r" вместо этого (по умолчанию), файл будет открыт в текстовом режиме, и f.read() вернёт объекты str, а не bytes объекты.

Не могу использовать os.read() для трубы, созданной с os.popen(); почему?

os.read() - функция низкого уровня, принимающая дескриптор файла, маленькое целое число, представляющее открытый файл. os.popen() создаёт высокоуровневый объект файла, тот же тип, возвращаемый встроенной функцией open(). Таким образом, чтобы прочитать n байт из трубы p, созданной с помощью os.popen(), вам нужно использовать p.read(n).

Как получить доступ к последовательному (RS232) порту?

Для Win32, OSX, Linux, BSD, Jython, IronPython:

pyserial

Для Unix, см. пост на Usenet от Митча Чепмена:

https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com

Почему закрытие sys.stdout (stdin, stderr) не закрывает его на самом деле?

Python объекты файлов представляют собой высокоуровневый уровень абстракции на низкоуровневых дескрипторах файлов C.

Для большинства объектов файлов, которые вы создаёте в Python с помощью встроенной функции open(), f.close() помечает объект файла Python как закрытый с точки зрения Python, а также обеспечивает закрытие лежащего в основе дескриптора файла C. Это также происходит автоматически в деструкторе f, когда f становится мусором.

Но stdin, stdout и stderr обрабатываются Python специально, из-за специального статуса, также присвоенного им C. Выполнение sys.stdout.close() помечает объект файла на уровне Python как закрытый, но не закрывает связанный дескриптор файла C.

Чтобы закрыть дескриптор файла C для одного из этих трёх, сначала убедитесь, что вы действительно хотите это сделать (например, вы можете спутать модули расширения, пытающиеся выполнить ввод-вывод). Если это так, используйте os.close():

os.close(stdin.fileno())
os.close(stdout.fileno())
os.close(stderr.fileno())

Или вы можете использовать числовые константы 0, 1 и 2 соответственно.

Программирование сетей/Интернета

Какие инструменты WWW доступны для Python?

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

Сводка доступных фреймворков поддерживается Полом Бодди по адресу https://wiki.python.org/moin/WebProgramming.

Кэмерон Лейрд поддерживает полезный набор страниц о веб-технологиях Python по адресу https://web.archive.org/web/20210224183619/http://phaseit.net/claird/comp.lang.python/web_python.

Как можно имитировать отправку формы CGI методом POST?

Мне нужно получить веб-страницы, которые являются результатом отправки формы методом POST. Есть ли готовый код, который позволил бы мне это сделать легко?

Да. Вот простой пример, использующий urllib.request:

#!/usr/local/bin/python

import urllib.request

# build the query string
qs = "First=Josephine&MI=Q&Last=Public"

# connect and send the server a path
req = urllib.request.urlopen('http://www.some-server.out-there'
                             '/cgi-bin/some-cgi-script', data=qs)
with req:
    msg, hdrs = req.read(), req.info()

Обратите внимание, что в общем случае для операций POST с кодировкой процентов строки запроса необходимо привести к каноническому виду с помощью urllib.parse.urlencode(). Например, для отправки name=Guy Steele, Jr.:

>>> import urllib.parse
>>> urllib.parse.urlencode({'name': 'Guy Steele, Jr.'})
'name=Guy+Steele%2C+Jr.'

См. также

Руководство по получению ресурсов интернета с помощью пакета urllib для подробных примеров.

Какой модуль следует использовать для генерации HTML?

Вы можете найти коллекцию полезных ссылок на странице вики Программирование веб-приложений.

Как отправить почту из скрипта Python?

Используйте стандартный модуль библиотеки smtplib.

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

import sys, smtplib

fromaddr = input("From: ")
toaddrs  = input("To: ").split(',')
print("Enter message, end with ^D:")
msg = ''
while True:
    line = sys.stdin.readline()
    if not line:
        break
    msg += line

# The actual mail send
server = smtplib.SMTP('localhost')
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

Альтернативный вариант, доступный только в Unix, использует sendmail. Расположение программы sendmail варьируется в зависимости от системы; иногда это /usr/lib/sendmail, иногда /usr/sbin/sendmail. Справка по sendmail поможет вам. Вот пример кода:

import os

SENDMAIL = "/usr/sbin/sendmail"  # sendmail location
p = os.popen("%s -t -i" % SENDMAIL, "w")
p.write("To: receiver@example.com\n")
p.write("Subject: test\n")
p.write("\n")  # blank line separating headers from body
p.write("Some text\n")
p.write("some more text\n")
sts = p.close()
if sts != 0:
    print("Sendmail exit status", sts)

Как избежать блокировки в методе connect() сокета?

Модуль select обычно используется для работы с асинхронным вводом-выводом в сокетах.

Чтобы предотвратить блокировку подключения TCP, вы можете установить сокет в режим без блокировки. Затем при вызове connect(), либо подключение будет установлено немедленно (маловероятно), либо возникнет исключение, содержащее номер ошибки в виде .errno. errno.EINPROGRESS указывает на то, что соединение в процессе, но еще не завершено. Разные операционные системы возвращают различные значения, поэтому вам нужно проверить, что возвращается на вашей системе.

Вы можете использовать метод connect_ex(), чтобы избежать создания исключения. Он просто вернет значение errno. Чтобы выполнить опрос, вы можете снова вызвать connect_ex() позже — 0 или errno.EISCONN означают, что вы подключены — или вы можете передать этот сокет в select.select(), чтобы проверить, можно ли с ним выполнять запись.

Примечание

Модуль asyncio предоставляет общее многопоточное и многозадачное асинхронное решение, которое можно использовать для написания неблокирующего сетевого кода. Библиотека Twisted от сторонних разработчиков является популярным и функциональным альтернативным вариантом.

Базы данных

Есть ли какие-либо интерфейсы к пакетам баз данных в Python?

Да.

Интерфейсы к базам данных на диске, таким как DBM и GDBM, также включены в стандартный Python. Также имеется модуль sqlite3, который предоставляет лёгкую реляционную базу данных на диске.

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

Как реализовать персистентные объекты в Python?

Модуль библиотеки pickle решает эту проблему очень общим способом (хотя вы по-прежнему не можете сохранять такие вещи, как открытые файлы, сокеты или окна), а модуль библиотеки shelve использует pickle и (g)dbm для создания персистентных отображений, содержащих произвольные объекты Python.

Математика и численные методы

Как сгенерировать случайные числа в Python?

Стандартный модуль random реализует генератор случайных чисел. Использование простое:

import random
random.random()

Это возвращает случайное число с плавающей точкой в диапазоне [0, 1).

В этом модуле также есть много других специализированных генераторов, таких как:

  • randrange(a, b) выбирает целое число в диапазоне [a, b).
  • uniform(a, b) выбирает число с плавающей точкой в диапазоне [a, b).
  • normalvariate(mean, sdev) выбирает выборку из нормального (гауссова) распределения.

Некоторые функции более высокого уровня непосредственно работают со последовательностями, например:

  • choice(S) выбирает случайный элемент из заданной последовательности.
  • shuffle(L) перемешивает список на месте, т.е. случайным образом переупорядочивает его.

Также есть класс Random, который можно использовать для создания независимых генераторов случайных чисел.

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/faq/library.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API