Как сделать ссылку в питоне

Как открыть ссылку в Python. Работа с WebBrowser и решение проблемы с Internet Explorer

В ходе работы над курсачом для универа столкнулся со стандартным модулем Python — WebBrowser. Через этот модуль я хотел реализовать работу голосового помощника — Lora с дефолтным браузером, но всё пошло не так гладко как ожидалось. Давайте для начала расскажу вам что это за модуль и как он вообще работает.

WebBrowser — это вшитый в Python модуль, который предоставляет собой высокоуровневый интерфейс, позволяющий просматривать веб-документы.

Для начала работы импортируйте модуль командой:

Теперь возникает выбор как открыть ссылку. Есть два стула:

1. Написать через одну строчку:

Если new = 0, URL-адрес открывается, если это возможно, в том же окне браузера. Если переменная new = 1, открывается новое окно браузера, если это возможно. Если new = 2, открывается новая страница браузера («вкладка»), если это возможно.

Значение autoraise можно смело пропускать, ибо оно открывает браузер поверх всех окон, а большинство современных браузеров плюёт на эту переменную даже в значении False.

2. Не мучиться с запоминанием параметров new и писать по-человечески:

Данная конструкция открывает URL-адрес в новом ОКНЕ браузера по умолчанию, если это возможно, в противном случае откроет URL-адрес в единственном окне браузера.

В этом случае URL-адрес откроется на новой странице (”tab») браузера по умолчанию, если это возможно, в противном случае эквивалентно open_new ().

Грубо говоря, вы просто указываете какой браузер вам использовать.

Например, открытие новой вкладки в Google Chrome:

Таблица названий браузеров:

Type NameClass Name
‘mozilla’Mozilla(‘mozilla’)
‘firefox’Mozilla(‘mozilla’)
‘netscape’Mozilla(‘netscape’)
‘galeon’Galeon(‘galeon’)
‘epiphany»Galeon(‘epiphany’)
‘skipstone’BackgroundBrowser(‘skipstone’)
‘kfmclient’Konqueror()
‘konqueror»Konqueror()
‘kfm’Konqueror()
‘mosaic’BackgroundBrowser(‘mosaic’)
‘opera’Opera()
‘grail’Grail()
‘links’GenericBrowser(‘links’)
‘elinks’Elinks(‘elinks’)
‘lynx’GenericBrowser(‘lynx’)
‘w3m’GenericBrowser(‘w3m’)
‘windows-default’WindowsDefault
‘macosx’MacOSX(‘default’)
‘safari’MacOSX(‘safari’)
‘google-chrome’Chrome(‘google-chrome’)
‘chrome»Chrome(‘chrome’)
‘chromium»Chromium(‘chromium’)
‘chromium-browser’Chromium(‘chromium-browser’)

Мы указали путь к Google Chrome, назвали его и теперь все ссылки открываются только в нём. Надеюсь немного разобрались с модулем WebBrowser и теперь перейдём к моей маленькой проблеме.

Проблема

Как говорилось ранее, для курсового проекта я выбрал создание голосового ассистента. Хотелось его научить переходить по ссылкам и искать информацию в поисковике. Конечно можно было бы «напиповать» множество библиотек для этого, но принципиально хотелось реализовать это через стандартный модуль WebBrowser.

Так как у большинства современных браузеров строка ввода ссылки и поисковая строка это одно и то же, то, казалось бы, можно просто передать запрос туда же, куда передаётся ссылка.

По логике этого кода должны открыться две вкладки:

Раз нам позволяют открывать только ссылки в дефолтном браузере, так и будем открывать только ссылки.

Шаги решения

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

Следовательно, мы будем искать точку и пробел в том, что ввёл пользователь. Реализовать мы сможем это благодаря модулю re, который также изначально встроен в Python. Python предлагает две разные примитивные операции, основанные на регулярных выражениях: match выполняет поиск паттерна в начале строки, тогда как search выполняет поиск по всей строке. Мы воспользуемся операцией search.

Немного объясню код.

Пользователь вводит ссылку или текст запроса в переменную call.

Первое условие проверяет переменную call на точку внутри неё. Символ ‘\’ обязателен, иначе модуль не понимает, что перед ним символ точка.

В этом условии всё тоже самое что и в первом, но проверка ведётся уже на пробел. А пробел говорит о том, что перед нами поисковой запрос.

А else, в свою очередь, присваивает всё что написал пользователь без пробелов и точек в поисковый запрос.

Проверка на пробел является обязательной, иначе WebBrowser открывает Internet Explorer.

Источник

Как сделать ссылку в питоне

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

[Черновик] Python 3, объекты, ссылки и пространства имён

На форуме БУ нередко сталкиваюсь с игроделами, которые пытаются писать скрипты методом научного тыка (а иногда даже ненаучного) и бездумным переделыванием других скриптов. Полагая, что это происходит из-за непонимания сути питоновых объектов, я попытаюсь наглядно показать, что вообще творится в питоне во время создания и изменения всяких разных переменных и классов.

(Мне почему-то постоянно говорят, что в BGE питон какой-то особенный и «дайте мне урок на блендеровый питон» и всё такое, мне уже начинает надоедать писать: ОБЫЧНЫЙ ПИТОН И ПИТОН В БЛЕНДЕРЕ АБСОЛЮТНО ОДИНАКОВЫЕ И СОВЕРШЕННО НИЧЕМ НЕ ОТЛИЧАЮТСЯ! В BGE лишь можно импортировать модуль bge, но и для него верно абсолютно всё написанное ниже и в любых других уроках по питону.)

В Python всё является объектом. Массивы, классы, строки, числа, функции, модули, типы и даже None являются полноценными объектами, которые содержат в себе различные атрибуты и методы.

Объекты сами по себе ниоткуда не берутся. При запуске скрипта гарантировано присутствуют лишь следующие объекты:
__builtins__
__doc__
__name__
__package__

И с ними сразу можно что-то делать:

И даже Blender Game Engine не добавляет никаких объектов: ни cont, ни scene, ни obj никакие ниоткуда сами не берутся: их должен доставать откуда-то сам скрипт. (А делается это импортированием модуля bge и вызовом оттуда нужных функций вроде bge.logic.getCurrentController().)

Объект __builtins__ — особый объект, он содержит в себе все стандартные типы и функции. Когда вы пишете:

то на самом деле выполняется примерно следующее:

По сути через этот __builtins__ всё и работает, и можно, например, что-нибудь в нём сломать (например, тот же импорт).

При создании переменной (любой: хоть число, хоть массив, хоть модуль, хоть None — у нас всё объекты) в неё записывается ссылка на объект, а сам объект валяется где-то в оперативной памяти далеко от самой переменной со ссылкой.

Схематично такое выглядит так:
Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

(Сами переменные, разумеется, тоже хранятся где-то в оператинвой памяти, но во избежание загромождения рисунка я буду рисовать их (и иногда сами объекты) отдельно.)

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

Получится следующее:
Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Соответственно, если мы попробуем в объекте что-нибудь поменять, обе переменные всё равно будут возвращать одно и то же.

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

И сам объект можно рассматривать как кучку переменных, доступ к которым можно получить с помощью этой самой точки. Собственно выше я и подменил значение переменной __builtins__.__import__ на своё:
Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Удалить объект нельзя, можно лишь удалить все ссылки на него.

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Но, как правило, когда ссылок на объект не остаётся, просыпается сборщик мусора и всё удаляет.
Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Создание собственных объектов осуществляется созданием класса и экземпляров этого класса. Класс тоже является объектом.

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

(CPython заранее создаёт объекты с некоторыми маленькими числами, чтобы побыстрее работало)

А вот дальше начинается магия. При создании экземпляра класса ОН БУДЕТ ПУСТОЙ, лишь переменная __class__ будет в нём.

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

В случае, если мы попытаемся обратиться к переменной a нашего obj, он при её отсутствии у себя вытянет её из своего класса:

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

А вот при попытке присвоить obj.a какое-нибудь число мы уже создадим переменную в самом объекте:

Собственно такое присваивание чаще всего и используют в функции __init__, которая вызывается каждый раз при создании экземпляра класса. Кстати, все функции, объявленные внутри класса, принимают первым аргументом объект, через который была вызвана функция.

С функциями всё то же самое, что и с объектами: в самом объекте их нет, они есть лишь в классе. И их можно вызывать прямо из класса.

И функцию в классе тоже можно подменить (но делать этого лучше не надо):

Но тут уже должен был возникнуть вопрос: что вообще за self, что за аргументы, откуда они взялись, где и как хранятся? Тут пора вводить понятие пространства имён. Оно определяет, какие переменные в каком месте будут видны. Ранее до появления функций мы работали с глобальным пространством имён. Все эти __builtins__, arr, Test, Num, obj1 и obj2 хранились именно в нём. Технически это самый обычный словарь, то есть абсолютно такой же объект, как и все остальные. Его можно получить с помощью функции globals() и творить с ним что угодно.

Помимо этого есть локальное пространство имён, которое у каждой функции своё. Вне функций локальное пространство имён совпадает с глобальным, и это можно проверить, получив его с помощь функции locals():

Так как это такие же самые объекты, их (точнее, ссылки) можно точно так же присвоить любой переменной. Не забывайте, что всё есть объекты, а переменные есть ссылки на эти объекты.

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

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

Разумеется, вне функции достучаться до её локального пространства имён никак нельзя (у каждого её вызова оно своё, функция может выполняться одновременно в нескольких потоках каждый со своим локальным пространством имён, может вообще не выполняться и так далее). (А вот к тому глобальному пространству имён, в котором она работает (у каждого модуля своё глобальное пространство имён), можно достучаться через атрибут __globals__)

При обращении к переменной приоритет имеет локальное пространство имён: если переменная с требуемым названием там существует, то возвращается значение из этого самого локального пространства имён; если её там нет, то из глобального; если и там нет, то питон ругается ошибкой. При создании переменных внутри функции они создаются в локальном пространстве имён (даже если такая же переменная есть в глобальном). Чтобы использовать только глобальную переменную, можно использовать ключевое слово globals. И далее в примерах всё сказанное выше:

Источник

Указатели в Python: в чём суть?

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Если вы когда-нибудь работали с такими низкоуровневыми языками, как С или С++, то наверняка слышали про указатели. Они позволяют сильно повышать эффективность разных кусков кода. Но также они могут запутывать новичков — и даже опытных разработчиков — и приводить к багам управления памятью. А есть ли указатели в Python, можно их как-то эмулировать?

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

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

С помощью этой статьи вы:

Почему в Python нет указателей?

Не знаю. Могут ли указатели существовать в Python нативно? Вероятно, но судя по всему, указатели противоречат понятию Zen of Python, потому что провоцируют неявные изменения вместо явных. Нередко указатели довольно сложны, особенно для новичков. Более того, они подталкивают вас к неудачным решениям или к тому, чтобы сделать что-нибудь действительно опасное, вроде чтения из области памяти, откуда вам не следовало считывать.

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

Чтобы разобраться с указателями в Python, давайте кратко пройдёмся по особенностями реализации языка. В частности, вам нужно понять:

Объекты в Python

Всё в Python является объектами. Например, откройте REPL и посмотрите, как используется isinstance() :

Этот код демонстрирует, что всё в Python — на самом деле объекты. Каждый объект содержит как минимум три вида данных:

Но не все объекты одинаковы. Есть одно важное отличие: объекты бывают изменяемые и неизменяемые. Понимание этого различия между типами объектов поможет вам лучше осознать первый слой луковицы, которая называется «указатели в Python».

Изменяемые и неизменяемые объекты

В Python есть два типа объектов:

ТипНеизменяемый?
intДа
floatДа
boolДа
complexДа
tupleДа
frozensetДа
strДа
listНет
setНет
dictНет

Как видите, многие из часто используемых примитивных типов являются неизменяемыми. Проверить это можно, написав кое-какой код на Python. Вам понадобится два инструмента из стандартной библиотеки:

Тип str тоже неизменяем:

И в этом случае s после операции += получает другой адрес памяти.

Бонус: Оператор += преобразовывается в различные вызовы методов.

Подробнее об этом рассказывается в документации по моделям данных Python.

При попытке напрямую изменить строковое значение s мы получим ошибку:

Обратная трассировка (последними отображаются самые свежие вызовы):

Сравните с изменяемым объектом, например, со списком:

Вот ещё одна демонстрация изменяемости списка с помощью присваивания:

Разбираемся с переменными

Переменные в Python в корне отличаются от переменных в C и C++. По сути, их просто нет в Python. Вместо переменных здесь имена.

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

Чтобы вам было проще разобраться, давайте посмотрим, как работают переменные в С, что они представляют, а затем сравним с работой имён в Python.

Переменные в C

Возьмём код, который определяет переменную x :

Исполнение это короткой строки проходит через несколько различных этапов:

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Обратите внимание, что расположение x не поменялось, только само значение. Это важно. Нам это говорит о том, что x — это место в памяти, а не просто имя.

Можно также рассматривать этот вопрос в рамках концепции владения. С одной стороны, x владеет местом в памяти. Во-первых, x — это пустая коробка, которая может содержать лишь одно число (integer), в котором могут храниться целочисленные значения.

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Теперь схема памяти выглядит так:

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

С именами в Python совершенно иная ситуация.

Имена в Python

В Python нет переменных, вместо них имена. Вы можете на своё усмотрение использовать термин «переменные», однако важно знать разницу между переменными и именами.

Давайте возьмём эквивалентный код из вышеприведённого примера на С и напишем его на Python:

Как и в C, в ходе исполнения этого код проходит несколько отдельных этапов:

PyObject определяется как C-структура, так что если вы удивляетесь, почему нельзя напрямую вызвать typecode или счётчик ссылок, то причина в том, что у вас нет прямого доступа к структурам. Вызовы методов вроде sys.getrefcount() могут помочь получить какие-то внутренние вещи.

Если говорить о памяти, то это может выглядеть таким образом:

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Если хотите присвоить x новое значение, попробуйте такой код:

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

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Эта иллюстрация демонстрирует, что x указывает на ссылку на объект и не владеет областью памяти, как раньше. Также вы видите, что команда x = 2338 является не присваиванием, а, скорее, привязкой (binding) имени x к ссылке.

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

В памяти появится новое имя, но не обязательно новый объект:

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Теперь вы видите, что новый Python-объект не создан, создано только новое имя, которое указывает на тот же объект. Кроме того, счётчик ссылок объекта увеличился на 1. Можете проверить эквивалентность идентичности объектов, чтобы подтвердить их одинаковость:

Этот код показывает, что x и y являются одним объектом. Но не ошибитесь: y всё ещё является неизменяемым. Например, вы можете выполнить с y операцию сложения:

После вызова сложения, вам вернётся новый Python-объект. Теперь память выглядит так:

Как сделать ссылку в питоне. Смотреть фото Как сделать ссылку в питоне. Смотреть картинку Как сделать ссылку в питоне. Картинка про Как сделать ссылку в питоне. Фото Как сделать ссылку в питоне

Был создан новый объект, и y теперь указывает на него. Любопытно, что точно такое же конечное состояние мы получили бы, если напрямую привязали y к 2339 :

После этого выражения мы получим такое конечное состояние памяти, как и при операции сложения. Напомню, что в Python вы не присваиваете переменные, а привязываете имена к ссылкам.

Об интернированных (intern) объектах в Python

Теперь вы понимаете, как создаются новые объекты в Python и как к ним привязываются имена. Пришло время поговорить об интернированных (interned) объектах.

У нас есть такой Python-код:

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

Но разве это не расточительно? Ну да, но эту цену вы платите за все замечательные преимущества Python. Вам не нужно думать об удалении подобных промежуточных объектов, и даже не нужно знать об их существовании! Прикол в том, что эти операции выполняются относительно быстро, и вы бы о них не узнали до этого момента.

Создатели Python мудро подметили эти накладные расходы и решили сделать несколько оптимизаций. Их результатом является поведение, которое может удивить новичков:

Какие объекты зависят от реализации Python? В CPython 3.7 интернированными являются:

Строки размером меньше 20 символов и содержащие ASCII-буквы, цифры или знаки подчёркивания будут интернированы, поскольку предполагается, что они будут применяться в качестве идентификаторов:

Здесь s1 и s2 указывают на один и тот же адрес в памяти. Если бы мы вставили не ASCII-букву, цифру или знак подчёркивания, то получили бы другой результат:

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

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

Интернированные объекты часто путают программистов. Просто запомните, что если начнёте сомневаться, то всегда можете воспользоваться id() и is для определения эквивалентности объектов.

Эмулирование указателей в Python

Тот факт, что указатели в Python отсутствуют нативно, не означает, что вы не можете воспользоваться преимуществами применения указателей. На самом деле есть несколько способов эмулирования указателей в Python. Здесь мы рассмотрим два из них:

Применение в качестве указателей изменяемых типов

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

Этот код берёт указатель на число ( *x ) и инкрементирует значение на 1. Вот основная функция для исполнения кода:

Один из способов репликации этого поведения в Python — использовать изменяемый тип. Например, применить список и изменить первый элемент:

Здесь add_one(x) обращается к первому элементу и увеличивает его значение на 1. Применение списка означает, что в результате мы получим изменённое значение. Так значит в Python существуют указатели? Нет. Описанное поведение стало возможным потому, что список — это изменяемый тип. Если вы попытаетесь использовать кортеж, то получите ошибку:

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

Этот код демонстрирует неизменяемость кортежа, поэтому он не поддерживает присваивание элементов.

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

Не забывайте, это лишь эмуляция поведения указателя, оно никак не связано с настоящими указателями в C и C++. Можно сказать, эти операции обходятся дороже, чем если бы они выполнялись в C или C++.

Использование объектов Python

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

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

То, что вы можете обратиться к этим именам как к атрибутам, означает, что вы абстрагированы от факта, что эти значения хранятся в словаре. К тому же вы делаете имена атрибутов более явными. Конечно, у вас должна быть возможность увеличивать значения:

Мы ввели два новых метода:

Вот полный исходный код класса Metrics :

Реальные указатели с помощью ctypes

Может быть, всё-таки есть указатели в Python, особенно в CPython? С помощью встроенного модуля ctypes можно создать настоящие указатели, как в C. Если вы не знакомы с ctypes, можете почитать статью Extending Python With C Libraries and the «ctypes» Module.

Вам это может понадобиться в тех случаях, когда нужно вызвать библиотеку С, которой необходимы указатели. Вернёмся к упомянутой выше С-функции add_one() :

libadd1.so должен лежать в вашей текущей директории. Можете с помощью ctypes загрузить его в Python:

В нашем случае сигнатурой функции является указатель на число, ctypes позволит задать это с помощью такого кода:

Здесь мы задаём сигнатуру функции, чтобы удовлетворить ожиданиям C. Теперь, если попробуем вызвать этот код с неправильным типом, то вместо непредсказуемого поведения получим красивое предупреждение:

Python бросает ошибку и объясняет, что add_one() хочет получить указатель, а не просто целое число. К счастью, в ctypes есть способ передавать указатели таким функциям. Сначала объявим целое число в стиле С:

Примечание: Словосочетание по ссылке является антонимом передаче переменной по значению.

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

Для вызова add_one() можете использовать этот код:

Отлично! Ваше число увеличилось на 1. Поздравляю, вы успешно использовали в Python настоящие указатели.

Заключение

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

Также мы узнали некоторые способы эмулирования указателей в Python:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *