- Класс и объект в Python
- Объектно-ориентированное программирование в Python
- Процедурно-ориентированный
- Объектно-ориентированный
- Создание класса в Python
- Атрибут:
- Метод:
- Конструктор:
- Что происходит при создании объекта с помощью класса?
- Конструктор с аргументами по умолчанию
- Сравнение объектов
- Атрибуты
- Атрибут
- Атрибуты функции
- Встроенные атрибуты класса
- Переменные класса
- Составляющие класса или объекта
- Python получить имя класса
- 6 ответов
- Как я могу получить имя объекта в Python?
- 15 ответов
- Вернуть имя функции
- Вернуть первое совпадающее имя объекта
- Вернуть все совпадающие имена объектов
Класс и объект в Python
Объектно-ориентированное программирование в Python
Python — это процедурно-ориентированный и одновременно объектно-ориентированный язык программирования.
Процедурно-ориентированный
«Процедурно-ориентированный» подразумевает наличие функций. Программист может создавать функции, которые затем используются в сторонних скриптах.
Объектно-ориентированный
«Объектно-ориентированный» подразумевает наличие классов. Есть возможность создавать классы, представляющие собой прототипы для будущих объектов.
Создание класса в Python
Синтаксис для написания нового класса:
- Для создания класса пишется ключевое слово class , его имя и двоеточие (:). Первая строчка в теле класса описывает его. (По желанию) получить доступ к этой строке можно с помощью ClassName.__doc__
- В теле класса допускается объявление атрибутов, методов и конструктора.
Атрибут:
Атрибут — это элемент класса. Например, у прямоугольника таких 2: ширина ( width ) и высота ( height ).
Метод:
- Метод класса напоминает классическую функцию, но на самом деле — это функция класса. Для использования ее необходимо вызывать через объект.
- Первый параметр метода всегда self (ключевое слово, которое ссылается на сам класс).
Конструктор:
- Конструктор — уникальный метод класса, который называется __init__ .
- Первый параметр конструктора во всех случаях self (ключевое слово, которое ссылается на сам класс).
- Конструктор нужен для создания объекта.
- Конструктор передает значения аргументов свойствам создаваемого объекта.
- В одном классе всегда только один конструктор.
- Если класс определяется не конструктором, Python предположит, что он наследует конструктор родительского класса.
Создание объекта с помощью класса Rectangle:
Что происходит при создании объекта с помощью класса?
При создании объекта класса Rectangle запускается конструктор выбранного класса, и атрибутам нового объекта передаются значения аргументов. Как на этом изображении:
Конструктор с аргументами по умолчанию
В других языках программирования конструкторов может быть несколько. В Python — только один. Но этот язык разрешает задавать значение по умолчанию.
Все требуемые аргументы нужно указывать до аргументов со значениями по умолчанию.
Сравнение объектов
В Python объект, созданный с помощью конструктора, занимает реальное место в памяти. Это значит, что у него есть точный адрес.
Если объект AA — это просто ссылка на объект BB , то он не будет сущностью, занимающей отдельную ячейку памяти. Вместо этого он лишь ссылается на местоположение BB .
Оператор == нужен, чтобы узнать, ссылаются ли два объекта на одно и то же место в памяти. Он вернет True , если это так. Оператор != вернет True , если сравнить 2 объекта, которые ссылаются на разные места в памяти.
Атрибуты
В Python есть два похожих понятия, которые на самом деле отличаются:
Стоит разобрать на практике:
Атрибут
Объекты, созданные одним и тем же классом, будут занимать разные места в памяти, а их атрибуты с «одинаковыми именами» — ссылаться на разные адреса. Например:
Python умеет создавать новые атрибуты для уже существующих объектов. Например, объект player1 и новый атрибут address .
Атрибуты функции
Обычно получать доступ к атрибутам объекта можно с помощью оператора «точка» (например, player1.name ). Но Python умеет делать это и с помощью функции.
Функция | Описание |
---|---|
getattr (obj, name[,default]) | Возвращает значение атрибута или значение по умолчанию, если первое не было указано |
hasattr (obj, name) | Проверяет атрибут объекта — был ли он передан аргументом «name» |
setattr (obj, name, value) | Задает значение атрибута. Если атрибута не существует, создает его |
delattr (obj, name) | Удаляет атрибут |
Встроенные атрибуты класса
Объекты класса — дочерние элементы по отношению к атрибутам самого языка Python. Таким образом они заимствуют некоторые атрибуты:
Атрибут | Описание |
---|---|
__dict__ | Предоставляет данные о классе коротко и доступно, в виде словаря |
__doc__ | Возвращает строку с описанием класса, или None , если значение не определено |
__class__ | Возвращает объект, содержащий информацию о классе с массой полезных атрибутов, включая атрибут __name__ |
__module__ | Возвращает имя «модуля» класса или __main__ , если класс определен в выполняемом модуле. |
Переменные класса
Переменные класса в Python — это то же самое, что Field в других языках, таких как Java или С#. Получить к ним доступ можно только с помощью имени класса или объекта.
Для получения доступа к переменной класса лучше все-таки использовать имя класса, а не объект. Это поможет не путать «переменную класса» и атрибуты.
У каждой переменной класса есть свой адрес в памяти. И он доступен всем объектам класса.
Составляющие класса или объекта
В Python присутствует функция dir , которая выводит список всех методов, атрибутов и переменных класса или объекта.
Источник
Python получить имя класса
Итак, у меня есть проблема, я хочу получить имя класса Python следующим образом:
Однако, похоже, что __class__.__name__ на самом деле еще не существует в то время, когда myName создано. Поэтому я был вынужден поместить это в функцию __init__() , например так:
Но это имеет большую проблему, потому что я не могу получить имя класса, пока не создаю его экземпляр, я настаиваю на создании нескольких гигабайт данных для каждого экземпляра класса, который будет сохранен в saveDirectory, поэтому он может использовать повторно позже. Так что я на самом деле не хочу идти дальше с моим текущим решением.
Есть ли способ получить имя класса, как я задумал? Или я просто сплю?
Спасибо, ребята, за ваши отличные предложения. Я собираюсь потратить немного времени на изучение метаклассов. В противном случае я, вероятно, создам словарь глобально и вместо этого буду ссылаться на эти экземпляры классов.
6 ответов
Единственный способ сделать то, что вы пытаетесь сделать во время определения класса, — это использовать метакласс :
Или на Python 3.x:
Это определенно менее понятно, чем просто использование следующего:
Просто использовать метод?
Или у вас может быть атрибут класса, указывающий каталог сохранения; меньше магии, как правило, хорошо. Кроме того, вы можете изменить имя класса позже, не нарушая хранилища.
Кроме того, что? Гигабайт?!
Я думаю, что то, что вы делаете, невозможно, потому что класс даже не существует, когда вы делаете:
myName = (get class name here automatically)
Но вскоре после того, как класс был интерпретирован, вы можете передать объект класса другой функции сделать работу за вас.
Кроме метакласса в ответе FJ , я могу вспомнить два других пути. Я начну с того, что выглядит лучше. Вам не нужно использовать метакласс; иногда дескриптор совершенно адекватен.
С другой стороны, если вам действительно нужно имя класса из внутри тела класса (маловероятно), вы можете отслеживать стек вызовов. Имя класса, как оно выглядит в исходном коде, находится на объекте кода, выполняемого по определению класса:
Из представленных на данный момент только этот последний позволяет использовать имя в виде строки внутри тела класса. К сожалению, это работает не во всех версиях Python. в частности, IronPython не реализует самоанализ стека вызовов, так как он не доступен в DLR.
Есть способ получить его, не анализируя стек, переносимо. Это похоже на ответ, предоставленный F J, использующий метакласс, но вместо этого использует функцию __prepare__ , доступную в Python 3:
попробуй это. Вы можете ссылаться на свой текущий класс с помощью _class . (Я использую Python 2.7)
Начиная с python 3.3, вы можете использовать __qualname__ переменная:
Источник
Как я могу получить имя объекта в Python?
Есть ли способ получить имя объекта в Python? Например:
Редактировать . Некоторый контекст:
На самом деле я создаю список функций, которые я могу указать с помощью командной строки.
Я получаю имя функции из командной строки и хочу вызвать соответствующую функцию:
И причина, по которой я хочу получить имя функции, заключается в том, что я хочу создать fun_dict , не записывая имена функций дважды, поскольку это кажется хорошим способом создания ошибок. Что я хочу сделать, это:
Таким образом, мне нужно написать имена функций только один раз.
15 ответов
Объекты не обязательно имеют имена в python, поэтому вы не можете получить имя. Обычно объекты имеют атрибут __name__ в тех случаях, когда у них есть имя, но это не является частью стандартного python, и большинство встроенных типов не имеют его.
Когда вы создаете переменную, такую как x, y, z выше, эти имена просто действуют как «указатели» или «ссылки» на объекты. Сам объект не знает, какое имя вы используете для него, и вы не можете легко (если вообще) получить имена всех ссылок на этот объект.
Обновление: однако функции имеют __name__ (если они не лямбда-выражения), поэтому в этом случае вы можете сделать:
У Python есть имена, которые отображаются на объекты в хэш-карте, называемой пространством имен. В любой момент времени имя всегда относится только к одному объекту, но на один объект может ссылаться любое произвольное количество имен. Учитывая имя, для хэш-карты очень эффективно искать единственный объект, к которому относится это имя. Однако, учитывая объект , на который, как уже упоминалось, можно ссылаться по нескольким именам, не существует эффективного способа поиска имен, которые к нему относятся. Что вам нужно сделать, так это перебрать все имена в пространстве имен, проверить каждое из них по отдельности и посмотреть, соответствует ли оно вашему заданному объекту. Это легко сделать с помощью понимания списка:
В результате будет получен список строк, содержащих имена всех локальных «переменных», которые в настоящее время сопоставлены с объектом myobj .
Конечно, locals() можно заменить любым dict , который вы хотите найти по именам, которые указывают на данный объект. Очевидно, что этот поиск может быть медленным для очень больших пространств имен, потому что они должны быть пройдены полностью.
Вот мой ответ, я также использую globals (). Items ()
Я добавил исключение_ слова, потому что я хочу отфильтровать слово, используемое в цикле for. Если вы не добавили его, ключевое слово в цикле for может запутать эту функцию, иногда ключевое слово «each_item» в следующем случае может отображаться в результате функции, в зависимости от того, что вы сделали с вашим циклом.
Надеюсь, это поможет.
Вы определяете class и добавляете приватную функцию Unicode, вставляете class как
Конечно, вы должны добавить дополнительную переменную self.name , которая является именем объекта.
Я наткнулся на эту страницу, задаваясь вопросом о том же вопросе.
Как уже отмечали другие, достаточно просто извлечь атрибут __name__ из функции, чтобы определить имя функции. Это немного сложнее с объектами, которые не имеют разумного способа определения __name__ , то есть базовых / примитивных объектов, таких как экземпляры базовой строки, целые, длинные и т. Д.
Короче говоря, вы могли бы использовать модуль inspect, чтобы сделать обоснованное предположение о том, какой это, но вам, вероятно, придется знать, в каком кадре вы работаете / пройти по стеку, чтобы найти правильный. Но я бы не хотел представить, как весело будет пытаться справиться с кодом eval / exec.
Обычно, когда вы хотите сделать что-то подобное, вы создаете класс для хранения всех этих функций и называете их с каким-то четким префиксом cmd_ или подобным. Затем вы берете строку из команды и пытаетесь получить этот атрибут из класса с префиксом cmd_ . Теперь вам нужно всего лишь добавить новую функцию / метод в класс, и он будет доступен вашим посетителям. И вы можете использовать строки документа для автоматического создания текста справки.
Как описано в других ответах, вы можете использовать тот же подход с globals() и обычными функциями в вашем модуле, чтобы более точно соответствовать тому, что вы просили.
Что-то вроде этого:
Имена переменных можно найти в словах globals () и locals (). Но они не дадут вам то, что вы ищете выше. «bla» будет содержать значение каждого элемента my_list, а не переменной.
Используйте обратный дикт.
Обратный dict отобразит каждую ссылку на функцию на точное имя, которое вы дали ей в fun_dict, которое может быть или не быть тем именем, которое вы использовали при определении функции. И эта техника обобщает на другие объекты, в том числе целые числа.
Для дополнительного удовольствия и безумия вы можете хранить прямое и обратное значения в одном и том же тексте. Я бы не стал этого делать, если бы вы отображали строки в строки, но если вы делаете что-то вроде ссылок на функции и строк, это не слишком безумно.
И причина, по которой я хочу получить имя функции, заключается в том, что я хочу создать fun_dict , не записывая имена функций дважды, поскольку это кажется хорошим способом создания ошибок.
Для этого у вас есть замечательная getattr функция, которая позволяет вам получить объект под известным именем. Так что вы могли бы сделать, например:
Обратите внимание, что, как уже отмечалось, объекты в целом не знают и не могут знать, какие переменные связаны с ними, функции, определенные с def , имеют имена в атрибуте __name__ (имя используется в <
Вот еще один способ думать об этом. Предположим, что существует функция name() , которая возвращает имя своего аргумента. Учитывая следующий код:
Что должно name(e[2]) вернуть и почему?
Как уже упоминали другие, это действительно сложный вопрос. Решения для этого не «один размер подходит всем», даже удаленно. Трудность (или легкость) действительно будет зависеть от вашей ситуации.
Я сталкивался с этой проблемой несколько раз, но совсем недавно при создании функции отладки. Я хотел, чтобы функция принимала некоторые неизвестные объекты в качестве аргументов и печатала их объявленные имена и содержимое. Получить содержимое легко, конечно, но объявленное имя — другая история.
Далее следует кое-что из того, что я придумал.
Вернуть имя функции
Определить имя функции очень просто, поскольку она имеет атрибут __name __ , содержащий объявленное имя функции.
Например, если вы создадите функцию def test_function(): pass , затем copy_function = test_function , а затем name_of_function(copy_function) , она вернет test_function .
Вернуть первое совпадающее имя объекта
Проверьте, имеет ли объект атрибут __name __ и верните его, если так (только объявленные функции). Обратите внимание, что вы можете удалить этот тест, так как имя все еще будет в globals() .
Сравните значение arg со значениями элементов в globals() и верните имя первого совпадения. Обратите внимание, что я отфильтровываю имена, начинающиеся с ‘_’.
Результат будет состоять из имени первого соответствующего объекта, в противном случае — None.
Вернуть все совпадающие имена объектов
- Сравните значение arg со значениями элементов в globals() и сохраните имена в списке. Обратите внимание, что я отфильтровываю имена, начинающиеся с ‘_’.
Результат будет состоять из списка (для нескольких совпадений), строки (для одного совпадения), в противном случае — Нет. Конечно, вы должны настроить это поведение по мере необходимости.
Если вы хотите получить имена функций, лямбда-выражений или других функциональных объектов, определенных в интерпретаторе, вы можете использовать dill.source.getname из dill . Он в значительной степени ищет метод __name__ , но в некоторых случаях он знает другую магию о том, как найти имя . или имя для объекта. Я не хочу вступать в спор о поиске единственного истинного имени для объекта python, что бы это ни значило.
Этот однострочник работает для всех типов объектов, если они находятся в globals() dict, которым они должны быть:
Или, что эквивалентно:
На самом деле это невозможно, так как может быть несколько переменных, имеющих одно и то же значение, или значение может не иметь переменной, или значение может иметь то же значение, что и переменная, только случайно.
Если вы действительно хотите это сделать, вы можете использовать
Однако было бы лучше, если бы вы сначала перебирали имена:
Источник