Как обратиться к переменной класса python
Перейти к содержимому

Как обратиться к переменной класса python

  • автор:

Как обратиться к переменной, находящейся внутри класса

Вытащить переменную без связки с Backtrader (в тестовом режиме и переменными в виде вручную заданных списков) одним из возможных методов по следующему примеру получается:

# 1 f = someClass(object) f.var1 = [1,2,3] f.var2 = 'asdf' someClass(f) 
# 2 XClass = someClass() XClass.close 

Через **kwargs тоже вытаскивается, но этот вариант даже не рассматриваю, т.к. списков очень много. Получить доступ к self.close находясь внутри класса возможно. Но принципиально нужно вытащить close как в представленном коде. Что я не так делаю?

Атрибуты класса и переменные экземпляра класса в Python

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

Python вызывает специальный метод __init__() , который называют конструктором класса, каждый раз при создании нового экземпляра класса.

class Dog: # атрибут данных (переменная класса), # общая для всех экземпляров класса kind = 'canine' def __init__(self, name): # переменная экземпляра класса # уникальна для каждого экземпляра self.name = name >>> d = Dog('Fido') >>> e = Dog('Buddy') # переменная `kind` будет общая для # всех экземпляров объекта `Dog` >>> d.kind # 'canine' >>> e.kind # 'canine' # переменная `name` будет уникальна # для каждого из экземпляров >>> d.name # 'Fido' >>> e.name # 'Buddy' 

Как говорилось в материале «Классы в языке Python», общие данные могут иметь неожиданный эффект при использовании изменяемых объектов, таких как списки и словари. Например, список tricks (трюки, которые может делать отдельная собака) в примере ниже не следует использовать как атрибут данных/переменную класса, потому что для всех экземпляров класса Dog будет использоваться только один атрибут данных tricks :

class Dog: # ошибочное использование атрибута tricks - # переменной класса tricks = [] def __init__(self, name): self.name = name def add_trick(self, trick): self.tricks.append(trick) >>> d = Dog('Fido') >>> e = Dog('Buddy') >>> d.add_trick('roll over') >>> e.add_trick('play dead') # неожиданно разделяется всеми собаками >>> d.tricks # ['roll over', 'play dead'] 

Правильный дизайн класса должен использовать tricks не как атрибут данных класса, а как переменную экземпляра класса:

class Dog: def __init__(self, name): self.name = name # создает новый пустой список # трюков для каждой собаки self.tricks = [] def add_trick(self, trick): self.tricks.append(trick) >>> d = Dog('Fido') >>> e = Dog('Buddy') >>> d.add_trick('roll over') >>> e.add_trick('play dead') >>> d.tricks # ['roll over'] >>> e.tricks # ['play dead'] 

Если одно и то же имя атрибута встречается как в экземпляре класса, так и в самом классе, то поиск атрибута определяет приоритет экземпляра класса:

>>> class Warehouse: purpose = 'storage' region = 'west' >>> w1 = Warehouse() >>> print(w1.purpose, w1.region) # storage west >>> w2 = Warehouse() >>> w2.region = 'east' >>> print(w2.purpose, w2.region) # storage east 

На атрибуты данных класса могут ссылаться как методы, так и обычные пользователи — «клиенты» объекта. Другими словами, классы не могут использоваться для реализации чисто абстрактных типов данных. Фактически, ничто в Python не позволяет принудительно скрывать данные — все основано на соглашении.

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

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

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

  • getattr(obj, name [, default]) — для доступа к атрибуту name объекта класса obj .
  • hasattr(obj, name) — проверить, есть ли в классе obj атрибут name .
  • setattr(obj, name, value) — задать атрибут name со значением value . Если атрибут не существует, он будет создан.
  • delattr(obj, name) — удалить атрибут name из объекта класса obj .
Встроенные атрибуты класса.

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

  • __dict__ — словарь, содержащий пространство имен класса.
  • __doc__ — строка документации класса. None если, документация отсутствует.
  • __name__ — имя класса.
  • __module__ — имя модуля, в котором определяется класс.
  • __bases__ — кортеж, содержащий базовые классы, в порядке их появления. Кортеж будет пустым, если наследование не было.
  • __mro__ — Порядок разрешения методов в множественном наследовании.

Где хранятся атрибуты класса и экземпляра класса?

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

class MyClass: class_attr = "Class" def __init__(self): self.instance_attr = "Instance" >>> my_object = MyClass() # атрибут экземпляра класса >>> my_object.__dict__ # # атрибут экземпляра класса >>> MyClass.__dict__['class_attr'] # 'Class' >>> my_object.class_attr 'Class' >>> my_object.instance_attr 'Instance' 
  • ОБЗОРНАЯ СТРАНИЦА РАЗДЕЛА
  • Пространство имен и область видимости в классах
  • Определение классов
  • Объект класса и конструктор класса
  • Создание экземпляра класса
  • Метод экземпляра класса
  • Что такое метод класса и зачем нужен
  • Что такое статический метод в классах Python и зачем нужен
  • Атрибуты класса и переменные экземпляра класса
  • Кэширование методов экземпляра декоратором lru_cache
  • Закрытые/приватные методы и переменные класса Python
  • Наследование классов
  • Множественное наследование классов
  • Абстрактные классы
  • Перегрузка методов в классе Python
  • Что такое миксины и как их использовать
  • Класс Python как структура данных, подобная языку C
  • Создание пользовательских типов данных
  • Специальные (магические) методы класса Python
  • Базовая настройка классов Python магическими методами
  • Настройка доступа к атрибутам класса Python
  • Дескриптор класса для чайников
  • Протокол дескриптора класса
  • Практический пример дескриптора
  • Использование метода .__new__() в классах Python
  • Специальный атрибут __slots__ класса Python
  • Специальный метод __init_subclass__ класса Python
  • Определение метаклассов metaclass
  • Эмуляция контейнерных типов в классах Python
  • Другие специальные методы класса
  • Как Python ищет специальные методы в классах
  • Шаблон проектирования Фабрика и его реализация

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

Author24 — интернет-сервис помощи студентам

Ребята учу тему ооп.Как передать переменную self.random_phrase, которую возвращает метод def get_random() в классе Phrases как аргумент для метода def phrase_іn_dіary() в классе Dіary. Чувствую как то серез конструктор, но не могу вкурить как.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import Godwіll import random class Phrases: def __init__(self): self.my_phrases = Godwіll.іnsіde_status_of_hero self.random_phrase = '' """ this method gets an argument - key from dіctіonary and returns a random phrase """ def get_random(self,arg): self.random_phrase = random.choice(self.my_phrases[arg]) return self.random_phrase class Dіary: def __init__(self): self.diarylist = [] def phrase_іn_dіary(self,arg): self.diarylist = [] ps = Phrases() ps.get_random('продает трофеи') dy = Dіary() dy.phrase_іn_dіary()
Здесь вы можете заказать любую студенческую или школьную работу.

Понимание переменных класса и экземпляра в Python 3

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

Переменные класса и экземпляра

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

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

Переменные класса

Переменные класса обычно являются переменными, которые являются общими для всех экземпляров. И они определены так:

class Student: teacher = 'Mrs. Jones' # переменная класса

Каждый экземпляр класса будет иметь одинаковое значение для этих переменных:

tom = Student() susan = Student() print(tom.teacher) >> "Mrs. Jones" print(susan.teacher) >> "Mrs. Jones"
Переменные экземпляра

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

class Student: teacher = 'Mrs. Jones' # переменная класса def __init__(self, name): self.name = name # переменная экземпляра

Посмотрите, как каждый экземпляр теперь содержит уникальное значение name:

tom = Student('Tom') susan = Student('Susan') print(tom.name) >> "Tom" print(susan.name) >> "Susan"
Резюме

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

Чего ожидать от переменных класса

Переменные класса являются общими для всех экземпляров класса. Напоминаем, что они определены так:

class Student: teacher = 'Mrs. Jones'

Иными словами, переменные класса ссылаются на одно и то же место в памяти. Смотрите следующее:

tom = Student() susan = Student() id(tom.teacher) == id(susan.teacher) >> True

Функция id возвращает адрес объекта в памяти для реализации CPython.

Таким образом, с помощью функции id мы можем подтвердить, что атрибут teacher ссылается на то же место в памяти.

Изменение переменной класса

Что произойдет, если мы изменим переменную класса даже после создания экземпляров?

tom = Student() tom.teacher >> Mrs. Jones Student.teacher = 'Mr. Smith' tom.teacher >> Mr. Smith

Как и следовало ожидать, поскольку переменная teacher ссылается на общее местоположение в памяти, она также обновляется в экземпляре.

Изменение переменной экземпляра

Это, вероятно, наиболее очевидное и ожидаемое поведение, поэтому не стесняйтесь пропустить этот шаг. Но я все же покажу несколько примеров для полноты.

Рассмотрим наш класс Student с переменными класса и экземпляра:

class Student: teacher = 'Mrs. Jones' def __init__(self, name): self.name = name

Мы видим, что каждый экземпляр класса имеет уникальный адрес памяти для имени:

tom = Student('Tom') susan = Student('Susan') id(tom.name) == id(susan.name) >> False

Как и следовало ожидать, обновление атрибута name в одном экземпляре не влияет на другой:

tom.name >> Tom susan.name >> Susan tom.name = 'Thomas' tom.name >> Thomas susan.name >> Susan

Переменные экземпляра переопределяют переменные класса (и методы)

Важно отметить, что переменные экземпляра (или атрибуты данных) переопределяют переменные класса.

tom = Student() susan = Student() id(tom.teacher) == id(susan.teacher) >> True

Что произойдет, если мы изменим атрибут teacher прямо в одном из случаев:

tom.teacher = 'Mr. Clark'

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

И, естественно, экземпляр Сьюзен не затронут:

tom.teacher >> Mr. Clark susan.teacher >> Mrs. Jones

Надеюсь, вы видите, как такое поведение может привести к путанице. По этой причине важно сохранять организованные имена переменных. Если переменная объявлена как переменная класса, она (обычно) не должна быть переопределена. Переменные экземпляра могут быть определены в очевидных местах, например, метод __init__. Часто хорошо придумать соглашение об именовании переменных. Например, методы класса должны быть глаголами, существительными переменных класса и существительными переменных экземпляра с префиксом «_».

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

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

Представьте, что мы хотим получить список результатов тестов студента. Мы могли бы составить такой класс:

class Student: teacher = 'Mrs. Jones' test_scores = [] def __init__(self, name): self.name = name def add_score(self, score): self.test_scores.append(score)

У нас есть переменная класса для хранения баллов, и у нас есть метод класса для добавления баллов. Теперь давайте добавим несколько баллов.

tom = Student('Tom') susan = Student('Susan') tom.add_score(90) susan.add_score(100)

Можете ли вы угадать, какую ошибку мы только что сделали?

tom.test_scores >> [90, 100]

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

Так что лучший класс может выглядеть так:

class Student: teacher = 'Mrs. Jones' def __init__(self, name): self.name = name self.test_scores = [] def add_score(self, score): self.test_scores.append(score)

И теперь наша проблема решена!

Заключение

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

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

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