Spec-Zone.ru › Python 3.11

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

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

    • Как найти модуль или приложение для выполнения задачи 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-формы (метод 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 — в Windows нет модуля curses.)

Модуль 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:

https://pypi.org/project/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 (METHOD=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?

Вы можете найти подборку полезных ссылок на странице вики «Веб-программирование» https://wiki.python.org/moin/WebProgramming.

Как отправить почту из сценария 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, который предоставляет лёгкую реляционную базу данных на диске.

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

Как реализовать постоянные объекты в 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/faq/library.html

Spec-Zone.ru

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