Как обратиться к переменной, находящейся внутри класса
Вытащить переменную без связки с 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 ищет специальные методы в классах
- Шаблон проектирования Фабрика и его реализация
Передать переменную в метод из другого класса

Ребята учу тему ооп.Как передать переменную 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)
И теперь наша проблема решена!
Заключение
Надеюсь, вы узнали разницу между переменными класса и экземпляра и что ожидать от каждой из них. Если я что-то упустил в этом руководстве или у вас есть отличные примеры путаницы переменных класса и экземпляра, пожалуйста, прокомментируйте ниже. Я был бы рад добавить их в это руководство!