Тип данных ссылка python

Указатели в Python подробно с практическими примерами

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

Что такое указатель в Python?

Указатель в Python – очень популярный и полезный инструмент для хранения адреса переменной. Если кто-то когда-либо работал с языком низкого уровня, таким как C, C ++, то, вероятно, были знакомы с указателями. Они очень эффективно управляют кодом. Для новичков это может быть немного сложно, но это одна из важных концепций программы. Однако, это может привести к различным ошибкам управления памятью. Таким образом, определение указателей:

«Указатели – это переменные, которые содержат адрес в памяти другой переменной. Переменные-указатели представлены звездочкой(*)».

Давайте посмотрим на следующий пример указателя на языке программирования C.

Пример – как использовать указатель в C

Address of o: 2686784 Value of o: 22 Address of pointer po: 2686784 Content of pointer po: 22 Address of pointer po: 2686784 Content of pointer po: 11 Address of o: 2686784 Value of o: 2

Указатели полезны, но они не представлены в Python. В этом разделе мы обсудим объектную модель Python и узнаем, почему указатели в Python не существуют. Мы также изучим различные способы моделирования указателей в Python.

Почему Python не поддерживает указатели

Точная причина отказа от поддержки указателя не ясна. Может ли указатель в Python существовать изначально? Основная концепция Python – его простота, но указатель нарушил дзен Python. Они достаточно сложны, особенно для новичков.

Указатели, как правило, усложняют код, а Python в основном ориентирован на удобство использования, а не на скорость. В результате Python не поддерживает указатель. Однако дает некоторые преимущества использования указателя.

Прежде чем разбираться в указателе в Python, нам необходимо иметь общее представление о следующих моментах.

Объекты

В Python все может являться объектом, даже классом, функцией, переменной и т. д. Каждый объект содержит как минимум три части данных.

Счетчик ссылок – используется для управления памятью. Чтобы получить дополнительную информацию об управлении памятью Python, прочтите статью «Управление памятью в Python».

Тип – слой CPython используется в качестве типа для обеспечения безопасности типов во время выполнения.

Наконец, есть значение, которое представляет собой фактическое значение, связанное с объектом.

Однако если мы углубимся в этот объект, мы обнаружим, что не все объекты одинаковы. Важное различие между типами объектов – неизменяемость и изменчивость. Прежде всего, нам нужно понять разницу между типами объекта, чтобы исследовать указатель в Python.

Читайте также:  Заголовок таблицы

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

Неизменяемые объекты не могут быть изменены, тогда как изменяемые объекты – могут. Давайте посмотрим на следующую таблицу общих типов и узнаем, являются ли они изменяемыми или нет.

Объекты Тип
Int Immutable
Float Immutable
Bool Immutable
List Mutable
Set Mutable
Complex Mutable
Tuple Immutable
Frozenset Immutable
Dict Mutable

Мы можем проверить тип вышеуказанных объектов с помощью метода id(). Этот метод возвращает адрес памяти объекта.

Мы печатаем следующие строки в среде REPL.

В приведенном выше коде мы присвоили x значение 10. если мы изменим это значение с заменой, мы получим новые объекты.

Мы модифицируем приведенный выше код и получаем в ответ новые объекты.

s = "java" print(id(s)) s += "Tpoint" print(s) id(s)
2315970974512 JavaTpoint 1977728175088

Опять же, мы изменяем значение x, добавляя новую строку, и получаем новый адрес памяти. Попробуем добавить строку прямо в s.

Traceback(most recent call last): File "C:/Users/DEVANSH SHARMA/PycharmProjects/MyPythonProject/python1.py", line 34, in s[0] = T NameError: name 'T' is not defined

Приведенный выше код возвращает ошибку, это означает, что строка не поддерживает мутацию. Итак, str – это неизменяемые объекты.

Теперь мы увидим изменяемый объект, такой как список.

my_list = [3, 4, 8] print(id(my_list)) my_list.append(4) print(my_list) print(id(my_list))
2571132658944 [3, 4, 8, 4] 2571132658944

Как мы видим в приведенном выше коде, my_list изначально имеет идентификатор, и мы добавили к списку цифру 5; my_list имеет тот же идентификатор, потому что список поддерживает изменчивость.

Понимание переменных Python

Способ определения переменных в Python сильно отличается от C или C ++. Переменная Python не определяет тип данных. На самом деле у Python есть имена, а не переменные.

Давайте разберемся, как переменная работает в C и как работает имя в Python.

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

В языке C переменная заключается в том, что она содержит значение или сохраняет значение. Он определяется типом данных. Давайте посмотрим на следующий код, определяющий переменную.

  • Выделите достаточно памяти для целого числа.
  • Мы присваиваем этой ячейке памяти значение 286.
  • X представляет это значение.

Если мы посмотрим на память –

Память

Как мы видим, x имеет ячейку памяти для значения 286. Теперь мы присвоим x новое значение.

Это новое значение перезаписывает предыдущее значение. Это означает, что переменная x изменчива. Расположение значения x такое же, но значение изменилось. Это важный момент, указывающий на то, что x – это ячейка памяти, а не только ее имя.

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

Переменная y создает новое поле с именем y, копирует значение из x в поле.

Новое поле с именем y

Имена в Python

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

Читайте также:  Add text with image html

Приведенный выше код разбивается во время выполнения.

  1. Необходимо создать PyObject.
  2. Установите для PyObject тип integer.
  3. Установите значение 289 для PyObject.
  4. Создайте имя под названием x.
  5. Укажите x на новый PyObject.
  6. Увеличьте счетчик ссылок PyObject на 1.

Это будет выглядеть так, как показано ниже.

Имена в Python

Мы можем понять внутреннюю работу переменной в Python. Переменная x указывает на ссылку на объект, и у него нет места в памяти, как раньше. Он также показывает, что x = 289 связывает имя x со ссылкой.

Теперь мы вводим новую переменную и присваиваем ей x.

В Python переменная y не создаст новый объект; это просто новое имя, указывающее на тот же объект. Refcount объекта также увеличился на единицу. Мы можем подтвердить это следующим образом.

Если мы увеличим значение y на единицу, оно больше не будет относиться к тому же объекту.

Это означает, что в Python мы не назначаем переменные. Вместо этого мы привязываем имена к ссылке.

Имитация указателей в Python

Python предоставляет альтернативные способы использования указателя. Эти два способа приведены ниже:

  • использование изменяемых типов в качестве указателей;
  • использование пользовательских объектов Python.

Давайте разберемся в данных способах.

Использование изменяемых типов в качестве указателя

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

В приведенном выше коде мы определили указатель * a, а затем увеличили значение на единицу. Теперь мы реализуем это с помощью функции main().

Мы можем смоделировать этот тип поведения, используя изменяемый тип Python. Разберитесь в следующем примере.

def add_one(x): x[0] += 1 y = [2337] add_one(y) y[0]

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

Traceback(most recent call last): File "", line 1, in File "", line 2, in add_one TypeError: 'tuple' object does not support item assignment

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

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

count = def car(): count["funcCalls"] += 1 def foo(): count["funCcalls"] += 1 car() foo() count["funcCalls"]

В приведенном выше примере мы использовали словарь count, который отслеживал количество вызовов функций. Когда вызывается функция foo(), счетчик увеличивается на 2, потому что dict изменяемый.

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

В предыдущем примере мы использовали dict для имитации указателя в Python, но иногда становится трудно запомнить все используемые имена ключей. Мы можем использовать собственный класс Python вместо словаря. Давайте разберемся в следующем примере.

Читайте также:  Apache sql php linux

class Pointer(object): def __init__(self): self._metrics =

В приведенном выше коде мы определили класс Pointer. Этот класс использовал dict для хранения фактических данных в переменной-члене _metrics. Это обеспечит изменчивость нашей программе. Сделать это можно следующим образом.

class Pointer(object): # . @property def funCalls(self): return self._metrics["func_calls"] @property def catPictures_served(self): return self._metrics["cat_pictures_served"]

Мы использовали декоратор @property. Если вы не знакомы с декораторами, посетите наш учебник по декораторам Python. Декоратор @property будет обращаться к funCalls и catPicture_served. Теперь мы создадим объект класса Pointer.

pt = Pointer() pt.funCalls() pt.catPicture_served

Здесь нам нужно увеличить эти значения.

class Pointer(object): # . def increament(self): self._metrices["funCalls"] += 1 def cat_pics(self): self._metrices["catPictures_served"] += 1

Мы определили два новых метода – increment() и cat_pics(). Мы изменили значения, используя эти функции в матрицах dict. Здесь мы можем изменить класс так же, как мы изменяем указатель.

pt = Pointer() pt.increment() pt.increment() pt.funCalls()

Модуль Python ctypes

Модуль Python ctypes позволяет нам создавать указатель C-типа в Python. Этот модуль полезен, если мы хотим вызвать функцию библиотеки C, для которой требуется указатель. Давайте разберемся в следующем примере.

В приведенной выше функции мы увеличили значение x на единицу. Предположим, мы сохраняем указанный выше файл с именем incrPointer.c и вводим следующую команду в терминал.

$ gcc -c -Wall -Werror -fpic incrPointer.c $ gcc -shared -o libinc.so incrPointer.o

Первая команда компилирует incrPointer.c в объект с именем incrPointer.o. Вторая команда принимает объектный файл и создает libinic.so для взаимодействия с ctypes.

import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL("./libinc.so") lib.increment

В приведенном выше коде ctypes.CDLL возвращает общий объект с именем libinic.so. Он содержит функцию incrPointer(). Если нам нужен указатель на функции, которые мы определяем в общем объекте, мы должны указать его с помощью ctypes. Давайте посмотрим на пример ниже.

inc = lib.increment ## defining the argtypes inc.argtypes = [ctypes.POINTER(ctypes.c_int)]

Если мы вызовем функцию с использованием другого типа, произойдет ошибка.

Traceback (most recent call last): File "", line 1, in ctypes.ArgumentError: argument 1: : expected LP_c_int instance instead of int

Это связано с тем, что incrPointer требует указатель, а ctypes – это способ передачи указателя в Python.

v – переменная C. Ctypes предоставляет метод byref(), который используется для передачи ссылки на переменную.

Мы увеличили значение, используя ссылочную переменную.

Заключение

Мы обсудили, что указатель отсутствует в Python, но мы можем реализовать то же действие с * изменяемым объектом. Мы также обсудили модули ctypes, которые могут определять указатель C в Python. Мы определили несколько отличных способов имитации указателя.

Источник

Оцените статью